<?php
/*********************************************************************************
 * The contents of this file are subject to the TimeTrex Public License Version
 * 1.1.0 ("License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at http://www.TimeTrex.com/TPL
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * All copies of the Covered Code must include on each user interface screen:
 *    (i) the "Powered by TimeTrex" logo and
 *    (ii) the TimeTrex copyright notice
 * in the same form as they appear in the distribution.  See full license for
 * requirements.
 *
 * The Original Code is: TimeTrex Open Source
 * The Initial Developer of the Original Code is TimeTrex Payroll Services
 * Portions created by TimeTrex are Copyright (C) 2004-2007 TimeTrex Payroll Services;
 * All Rights Reserved.
 *
 ********************************************************************************/
/*
 * $Revision: 2426 $
 * $Id: TimeTrexSoapServerUnAuthenticated.class.php 2426 2009-02-18 22:39:19Z ipso $
 * $Date: 2009-02-18 14:39:19 -0800 (Wed, 18 Feb 2009) $
 */

/**
 * @package Module_SOAP
 */
class TimeTrexSoapServerUnAuthenticated {

	function helloworld($text) {
		return "Hello World: $text - ". $_COOKIE['SessionID'] ."";
	}

	function getClientVersion() {
		if ( isset($_GET['v']) AND $_GET['v'] != '' ) {
			return $_GET['v'];
		}

		return FALSE;
	}

	//PING function to test internet connection.
	function ping() {
		Debug::Text('Ping: '. TTDate::getDate('DATE+TIME', time() ), __FILE__, __LINE__, __METHOD__,10);
		return TRUE;
	}

	function getTime() {
		TTDate::setTimeZone('GMT');
		return TTDate::getTime();
	}

	function getTimeOffset( $client_epoch ) {
		TTDate::setTimeZone('GMT');
		$server_epoch = TTDate::getTime();

		$offset = $client_epoch - $server_epoch;

		Debug::Text('Client Time: '.  TTDate::getDate('DATE+TIME', $client_epoch ) .' Server Time: '.  TTDate::getDate('DATE+TIME', $server_epoch ) .' Offset: '. $offset, __FILE__, __LINE__, __METHOD__,10);

		if ( $offset == 0 ) {
			$offset = 1;
		}

		return (int)$offset;
	}

	function getStationObject() {
		if ( $_GET['StationID'] == '' ) {
			return FALSE;
		}

		$slf = new StationListFactory();
		$slf->getByStationId( $_GET['StationID'] );
		$current_station = $slf->getCurrent();
		unset($slf);

		return $current_station;
	}

	function Login($user_name, $password = NULL, $type = NULL) {
		$authentication = new Authentication();

		Debug::text('User Name: '. $user_name .' Password Length: '. strlen($password) .' Type: '. $type, __FILE__, __LINE__, __METHOD__, 10);

		if ( $authentication->Login($user_name, $password, $type) === TRUE ) {
			$retval = $authentication->getSessionId();
			Debug::text('Success, Session ID: '. $retval, __FILE__, __LINE__, __METHOD__, 10);
			return $retval;
		}

		return FALSE;
	}

	//Check for updates each day... And on startup, and allow a menu option to force a check.
	function getLatestVersion() {
		return '2.5.4';
	}

	function isLatestVersion($current_version) {
		if ( $current_version == '' ) {
			return FALSE;
		}

		$current_version = trim($current_version);

		Debug::text('Current Version: '. $current_version .' Latest Version: '. $this->getLatestVersion(), __FILE__, __LINE__, __METHOD__, 10);

		if ( version_compare( $current_version, $this->getLatestVersion(), '<') == TRUE ) {
			Debug::text('Current version Returning FALSE!', __FILE__, __LINE__, __METHOD__, 10);
			return FALSE;
		}

		Debug::text('Current version Returning TRUE!', __FILE__, __LINE__, __METHOD__, 10);
		return TRUE;
	}

	function getLatestVersionURL() {
		if ( isset($_SERVER["HTTPS"]) ) {
			$prefix = 'https';
		} else {
			$prefix = 'http';
		}

		$retval = $prefix.'://'. $_SERVER["HTTP_HOST"].'/'.Environment::getBaseURL().'/help/Timetrex_Client.exe';

		Debug::text('Client URL: '. $retval , __FILE__, __LINE__, __METHOD__, 10);

		return $retval;
	}

	function getLatestVersionMD5() {
		$file_name = Environment::getBasePATH().'client/binary/Timetrex_Client_v'. $this->getLatestVersion().'.exe';
		Debug::text('File Name: '. $file_name, __FILE__, __LINE__, __METHOD__, 10);
		return md5_file($file_name);
	}

	//Ask server if its a good time to upgrade.
	//That way the server can take load in to account,
	//as well as check the schedule on this station, and make sure
	//people aren't about to punch in!
	//
	//Return offset in seconds of when to upgrade perhaps?
	//0 means now, 3600 means in one hour?
	//Or just keep returning false, and cache the data...
	//Returning a new offset is better I think, because that way
	//the 24hr timer can be sync'd to a good time to do the upgrades.

	function isGoodTimeToUpgrade( $station_id ) {
		Debug::Text('Checking isGoodTimeToUpgrade for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return 0;
		}

/*
		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			Debug::Text('Found Station!!', __FILE__, __LINE__, __METHOD__,10);
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();
			if ( $company_id == 1 ) {
				Debug::Text('Station is member of Company ID: 1... Upgrading', __FILE__, __LINE__, __METHOD__,10);
				return 0;
			}
		}
*/

		//Debug::Text('Not Good time to upgrade...', __FILE__, __LINE__, __METHOD__,10);

		//Always upgrade everyone from now on.
		return 0;

		/*
		if ( $station_id == '7800000021370B81' ) {
			return 0;
		} else {
			return 600;
		}
		*/
		/*
		//explain analyze select date_part('hour', time_stamp),count(*) from punch where station_id = 325 group by date_part('hour', time_stamp) order by date_part('hour', time_stamp);

		$cache->save(serialize($data), $station_id, 'isGoodTimeToUpgrade' );

		$retval = 5 * $data['count'];

		Debug::text('Returning Delay Seconds: '. $retval, __FILE__, __LINE__, __METHOD__, 10);

		return $retval;
		*/
	}

	//Just a function to log the update start.
	function startingUpgrade( $station_id ) {
		Debug::text('Starting Upgrade for Station ID: '. $station_id .' Date: '. TTDate::getDate('DATE+TIME', TTDate::getTime() ), __FILE__, __LINE__, __METHOD__, 10);

		return TRUE;

	}

	function isLatestData( $station_id, $last_check_epoch ) {
		//$last_check_epoch = strtotime('27-Jan-06 14:20');

		Debug::Text('Checking for latest User/Branch/Dept data for Station ID: '. $station_id  .' Last Checked: '. TTDate::getDate('DATE+TIME', $last_check_epoch ) .' ('.$last_check_epoch.')', __FILE__, __LINE__, __METHOD__,10);

		//If last_check_epoch is NULL, or 0, return FALSE to force an update.
		if ( $last_check_epoch == '' OR $last_check_epoch == 0 ) {
			return FALSE;
		}

		//Gets all users allowed to punch in/out from this station
		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {

			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();

			Debug::Text('Found Station!! ID: '. $s_obj->getId() .' Company ID: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

			if ( $company_id != FALSE ){

				$ulf = new UserListFactory();
				$modified_arr['user_modified'] = $ulf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
				Debug::Text('Are Users Modified: '. (int)$modified_arr['user_modified'], __FILE__, __LINE__, __METHOD__,10);

				$blf = new BranchListFactory();
				$modified_arr['branch_modified'] = $blf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
				Debug::Text('Are Branches Modified: '. (int)$modified_arr['branch_modified'] , __FILE__, __LINE__, __METHOD__,10);

				$dlf = new DepartmentListFactory();
				$modified_arr['department_modified'] = $dlf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
				Debug::Text('Are Departments Modified: '. (int)$modified_arr['department_modified'] , __FILE__, __LINE__, __METHOD__,10);

				if ( version_compare( $this->getClientVersion(), '2.7.0', '>=' ) ) {
					$uilf = new UserIdentificationListFactory();
					$modified_arr['user_identifiers_modified'] = $uilf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
					Debug::Text('Are User Identifiers Modified: '. (int)$modified_arr['user_identifiers_modified'] , __FILE__, __LINE__, __METHOD__,10);
				}

				if ( getTTProductEdition() == TT_PRODUCT_PROFESSIONAL ) {
					$jlf = new JobListFactory();
					$modified_arr['job_modified'] = $jlf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
					Debug::Text('Are Jobs Modified: '. (int)$modified_arr['job_modified'], __FILE__, __LINE__, __METHOD__,10);
					if ( $modified_arr['job_modified'] == TRUE ) {
						$modified_arr['job_to_user_map_modified'] = TRUE;
						$modified_arr['job_to_job_item_map_modified'] = TRUE;
					}
				}

				if ( getTTProductEdition() == TT_PRODUCT_PROFESSIONAL ) {
					$jilf = new JobItemListFactory();
					$modified_arr['job_item_modified'] = $jilf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
					Debug::Text('Are Job Items Modified: '. (int)$modified_arr['job_item_modified'], __FILE__, __LINE__, __METHOD__,10);
				}

				$oflf = new OtherFieldListFactory();
				$modified_arr['other_field_modified'] = $oflf->getIsModifiedByCompanyIdAndDate( $company_id, $last_check_epoch);
				Debug::Text('Are Other Fields Modified: '. (int)$modified_arr['other_field_modified'], __FILE__, __LINE__, __METHOD__,10);

				return $modified_arr;
			}
		}

		return TRUE;
		//return FALSE;
	}

	function getClientConfig( $station_id ) {
		Debug::Text('Getting Client Settings for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		$data = array(
						'latest_version_schedule' => 3600,
						'latest_version_schedule_random' => 600,
						'latest_data_schedule' => 3600,
						'auto_submit_timeout' => 5,
						'auto_submit_timeout_increment' => 3,
						'auto_submit_timeout_max' => 20,
						'punch_dump_schedule' => 1600,
						'flap_offline_time' => 1600,
						'flap_window' => 600,
						'flap_trigger' => 5,
						'debug_verbosity' => 10,
						'upload_debug_verbosity' => 10,
						'punch_upload_batch' => 25,
						//'enable_keyboard_shortcuts' => TRUE,
					);

		return $data;
	}

	function getUsers( $station_id ) {
		Debug::Text('Getting Users for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		$permission = new Permission();

		//Gets all users allowed to punch in/out from this station
		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			Debug::Text('Found Station!!', __FILE__, __LINE__, __METHOD__,10);
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();

			if ( $company_id != FALSE ){
				Debug::Text('Found Company: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

				$ulf = new UserListFactory();
				$ulf->getByCompanyId( $company_id );
				if ( $ulf->getRecordCount() > 0 ) {
					Debug::Text('Found Users '. $ulf->getRecordCount() .' for Company: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

					$x=0;
					foreach( $ulf as $u_obj ) {
						//Debug::Text('User ID: '. $u_obj->getId() .' iButton ID: '. $u_obj->getiButtonId() , __FILE__, __LINE__, __METHOD__,10);
						$enable_job_tracking = $permission->Check('job', 'enabled', $u_obj->getId(), $u_obj->getCompany());
						//Debug::Text('Enable Job Tracking for User: '. $u_obj->getUserName() .' Result: '. (int)$enable_job_tracking, __FILE__, __LINE__, __METHOD__,10);

						if ( version_compare( $this->getClientVersion(), '2.7.0', '<' ) ) {

							//In offline punch mode, we use the system local time
							//as we assume it is in the proper timezone for the user.
							/*
							$u_obj_prefs = $u_obj->getUserPreferenceObject();
							if ( is_object( $u_obj_prefs ) ) {
								$time_zone = $u_obj_prefs->getTimeZone();
								$language = $u_obj_prefs->getLanguage();
							} else {
								$time_zone = NULL;
								$language = NULL;
							}
							*/

							$ibutton = FALSE;
							$finger_print_1 = FALSE;
							$finger_print_2 = FALSE;
							$finger_print_3 = FALSE;
							$finger_print_4 = FALSE;

							//Get User identification rows for ibutton and fingerprints.
							$uilf = new UserIdentificationListFactory();
							$uilf->getByUserIdAndTypeId( $u_obj->getId(), array(10,20) ); //iButton and Griaule Fingerprints.
							//Debug::Text('User Identication Records: '. $uilf->getRecordCount(), __FILE__, __LINE__, __METHOD__,10);
							if ( $uilf->getRecordCount() > 0 ) {
								foreach( $uilf as $ui_obj ) {
									if ( $ui_obj->getType() == 10 ) {
										Debug::Text('Found iButton... User:  '. $u_obj->getID() .' Number: '. $ui_obj->getNumber(), __FILE__, __LINE__, __METHOD__,10);
										$ibutton = $ui_obj->getValue();
									} elseif ( $ui_obj->getType() == 20) {
										Debug::Text('Found Griaule FingerPrint... User:  '. $u_obj->getID() .' Number: '. $ui_obj->getNumber(), __FILE__, __LINE__, __METHOD__,10);
										switch ( $ui_obj->getNumber() ) {
											case 10:
												$finger_print_1 = $ui_obj->getValue();
												break;
											case 20:
												$finger_print_2 = $ui_obj->getValue();
												break;
											case 30:
												$finger_print_3 = $ui_obj->getValue();
												break;
											case 40:
												$finger_print_4 = $ui_obj->getValue();
												break;
										}
									}
								}
							}

							$user_list["'$x'"] = array(
											'id' => (int)$u_obj->getId(),
											'ibutton_id' => $ibutton,
											'employee_number' => $u_obj->getEmployeeNumber(),
											'user_name' => $u_obj->getUserName(),
											'full_name' => $u_obj->getFullName(),
											'default_branch_id' => (int)$u_obj->getDefaultBranch(),
											'default_department_id' => (int)$u_obj->getDefaultDepartment(),
											//'country' => $u_obj->getCountry(),
											//'language' => $language,
											//'time_zone' => $time_zone,
											'finger_print_1' => $finger_print_1,
											'finger_print_2' => $finger_print_2,
											'finger_print_3' => $finger_print_3,
											'finger_print_4' => $finger_print_4,
											'enable_job_tracking' => $enable_job_tracking,
											);
						} else {
							$user_list["'$x'"] = array(
											'id' => (int)$u_obj->getId(),
											'employee_number' => $u_obj->getEmployeeNumber(),
											'user_name' => $u_obj->getUserName(),
											'full_name' => $u_obj->getFullName(),
											'default_branch_id' => (int)$u_obj->getDefaultBranch(),
											'default_department_id' => (int)$u_obj->getDefaultDepartment(),
											//'country' => $u_obj->getCountry(),
											//'language' => $language,
											//'time_zone' => $time_zone,
											'enable_job_tracking' => $enable_job_tracking,
											);
						}

						unset($enable_job_tracking, $time_zone, $language );
						$x++;
					}

					if ( isset($user_list) ) {
						Debug::Text('Returning User List!', __FILE__, __LINE__, __METHOD__,10);
						return $user_list;
					}
				}
			}
		}

		Debug::Text('Returning FALSE!', __FILE__, __LINE__, __METHOD__,10);

		return FALSE;
	}

	function getUserIdentifiers( $station_id ) {
		Debug::Text('Getting User Identifiers for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		//Gets all users allowed to punch in/out from this station
		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();

			if ( $company_id != FALSE ){
				$uilf = new UserIdentificationListFactory();

				if ( version_compare( $this->getClientVersion(), '3.0.0', '>=' ) ) {
					$uilf->getByCompanyIdAndTypeId( $company_id, array(10,25,30,40) ); //iButtons, LIBFP Fingerprints, Barcodes, Proximity Cards
				} else {
					$uilf->getByCompanyIdAndTypeId( $company_id, array(10,20,30,40) ); //iButtons, Griaule Fingerprints Barcodes, Proximity Cards
				}

				if ( $uilf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $uilf as $ui_obj ) {
						$identification_list["'$x'"] = array(
										'user_id' => (int)$ui_obj->getUser(),
										'type_id' => (int)$ui_obj->getType(),
										'number' => (int)$ui_obj->getNumber(),
										'value' => $ui_obj->getValue(),
										);
						$x++;
					}

					if ( isset($identification_list) ) {
						return $identification_list;
					}
				}
			}
		}

		return FALSE;
	}

	function getBranches( $station_id ) {
		Debug::Text('Getting Branches for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		//Gets all users allowed to punch in/out from this station
		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();

			if ( $company_id != FALSE ){
				$blf = new BranchListFactory();
				$blf->getByCompanyIdAndStatus( $company_id, 10 );
				if ( $blf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $blf as $b_obj ) {
						$branch_list["'$x'"] = array(
										'id' => (int)$b_obj->getId(),
										'manual_id' => (int)$b_obj->getManualID(),
										'name' => $b_obj->getName(),
										);
						$x++;
					}

					if ( isset($branch_list) ) {
						return $branch_list;
					}
				}
			}
		}

		return FALSE;
	}

	function getDepartments( $station_id ) {
		Debug::Text('Getting Departments for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		//Gets all users allowed to punch in/out from this station
		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();

			if ( $company_id != FALSE ) {
				$dlf = new DepartmentListFactory();
				$dlf->getByCompanyIdAndStatus( $company_id, 10 );
				if ( $dlf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $dlf as $d_obj ) {
						$department_list["'$x'"] = array(
										'id' => (int)$d_obj->getId(),
										'manual_id' => (int)$d_obj->getManualID(),
										'name' => $d_obj->getName(),
										);
						$x++;
					}

					if ( isset($department_list) ) {
						return $department_list;
					}
				}
			}
		}

		return FALSE;
	}

	function getJobs( $station_id ) {
		Debug::Text('Getting Jobs for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		if ( getTTProductEdition() != TT_PRODUCT_PROFESSIONAL ) {
			return FALSE;
		}

		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();
			Debug::Text('Company ID: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

			if ( $company_id != FALSE ) {
				//Gets all users allowed to punch in/out from this station
				$jlf = new JobListFactory();
				//$jlf->getByCompanyIdAndUserIdAndStatus( $company_id,  $current_user->getId(), array(10), TRUE );
				$jlf->getByStatusIdAndCompanyId( 10, $company_id);
				if ( $jlf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $jlf as $j_obj) {
						$job_list["'$x'"] = array(
										'id' => (int)$j_obj->getId(),
										'manual_id' => (int)$j_obj->getManualID(),
										'name' => $j_obj->getName(),
										);

						$x++;
					}

					if ( isset($job_list) ) {
						return $job_list;
					}
				}
			}

		}

		Debug::Text('Returning FALSE!', __FILE__, __LINE__, __METHOD__,10);

		return FALSE;
	}

	function getJobtoUserMap( $station_id ) {
		//If the user is not in the list, that means they are allowed to ALL jobs.
		Debug::Text('Getting JobToUser Map for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		if ( getTTProductEdition() != TT_PRODUCT_PROFESSIONAL ) {
			return FALSE;
		}

		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();
			Debug::Text('Company ID: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

			if ( $company_id != FALSE ) {
				//Gets all users allowed to punch in/out from this station
				$jualf = new JobUserAllowListFactory();
				//$jlf->getByCompanyIdAndUserIdAndStatus( $company_id,  $current_user->getId(), array(10), TRUE );
				$jualf->getByCompanyIdAndStatus( $company_id, 10);
				if ( $jualf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $jualf as $jua_obj) {
						$list["'$x'"] = array(
										'job_id' => (int)$jua_obj->getJob(),
										'user_id' => (int)$jua_obj->getUser(),
										);

						$x++;
					}

					if ( isset($list) ) {
						return $list;
					}
				}
			}

		}

		Debug::Text('Returning FALSE!', __FILE__, __LINE__, __METHOD__,10);

		return FALSE;
	}

	function getJobItems( $station_id ) {
		Debug::Text('Getting Jobs for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		if ( getTTProductEdition() != TT_PRODUCT_PROFESSIONAL ) {
			return FALSE;
		}

		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();
			Debug::Text('Company ID: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

			if ( $company_id != FALSE ) {
				//Gets all users allowed to punch in/out from this station
				$jilf = new JobItemListFactory();
				$jilf->getByCompanyId( $company_id );
				if ( $jilf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $jilf as $ji_obj) {
						$job_item_list["'$x'"] = array(
										'id' => (int)$ji_obj->getId(),
										'manual_id' => (int)$ji_obj->getManualID(),
										'name' => $ji_obj->getName(),
										);

						$x++;
					}

					if ( isset($job_item_list) ) {
						return $job_item_list;
					}
				}
			}

		}

		Debug::Text('Returning FALSE!', __FILE__, __LINE__, __METHOD__,10);

		return FALSE;
	}

	function getJobtoJobItemMap( $station_id ) {
		//If the job is not in the list, that means all items are allowed
		Debug::Text('Getting JobToUser Map for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		if ( getTTProductEdition() != TT_PRODUCT_PROFESSIONAL ) {
			return FALSE;
		}

		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();
			Debug::Text('Company ID: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

			if ( $company_id != FALSE ) {
				//Gets all users allowed to punch in/out from this station
				$jialf = new JobItemAllowListFactory();
				//$jlf->getByCompanyIdAndUserIdAndStatus( $company_id,  $current_user->getId(), array(10), TRUE );
				$jialf->getByCompanyIdAndStatus( $company_id, 10);
				if ( $jialf->getRecordCount() > 0 ) {
					$x=0;
					foreach( $jialf as $jia_obj) {
						$list["'$x'"] = array(
										'job_id' => (int)$jia_obj->getJob(),
										'job_item_id' => (int)$jia_obj->getItem(),
										);

						$x++;
					}

					if ( isset($list) ) {
						return $list;
					}
				}
			}

		}

		Debug::Text('Returning FALSE!', __FILE__, __LINE__, __METHOD__,10);

		return FALSE;
	}

	function getOtherFields( $station_id ) {
		Debug::Text('Getting Other Fields Map for Station ID: '. $station_id, __FILE__, __LINE__, __METHOD__,10);

		if ( $station_id == '' ) {
			return FALSE;
		}

		$slf = new StationListFactory();
		$slf->getByStationID( $station_id );
		if ( $slf->getRecordCount() > 0 ) {
			$s_obj = $slf->getCurrent();
			$company_id = $s_obj->getCompany();
			Debug::Text('Company ID: '. $company_id, __FILE__, __LINE__, __METHOD__,10);

			if ( $company_id != FALSE ) {
				$oflf = new OtherFieldListFactory();
				$retval = $oflf->getByCompanyIdAndTypeIdArray( $company_id, 15 );

				return $retval;
			}
		}

		Debug::Text('Returning FALSE!', __FILE__, __LINE__, __METHOD__,10);

		return FALSE;
	}

	function setClientLog( $data ) {
		global $config_vars;

		if ( !is_array($data) OR count($data) == 0 ) {
			return FALSE;
		}

		ksort($data);

		$base_dir = $config_vars['path']['log'] . DIRECTORY_SEPARATOR .'client' . DIRECTORY_SEPARATOR;
		$upload_time = time();

		Debug::Text('Setting Log Lines: '.count($data), __FILE__, __LINE__, __METHOD__,10);

		//Binary data could be coming in through this. Eric should Base64 encode his end
		//And Decode it here.

		//Log all data to log files based on station IDs. If no station id (ie: no probes plugged in)
		//Use IP address and send to a "generic" log.

		foreach( $data as $row_key => $row ) {
			//Debug::Text('Row Key: '. $row_key .' Date/Time: '. TTDate::getDate('DATE+TIME', $row['epoch']) .' Verbosity: '. $row['verbosity'] .' Station ID: '. $row['station_id'] .' Text: '. $row['msg'], __FILE__, __LINE__, __METHOD__,10);

			if ( $row['station_id'] == '' ) {
				$station_id = 'no_station_id';
			} else {
				$station_id = $row['station_id'];
			}

			$retarr[$station_id][] = '['.TTDate::getDate('DATE+TIME', $row['epoch']).'] ('. $row['verbosity'] .') - '. $row['msg']."\n";
		}

		foreach( $retarr as $station_id => $line_arr) {
			array_unshift( $line_arr, '---------------- Data Uploaded By: '. $_SERVER['REMOTE_ADDR'] .' At: '. TTDate::getDate('DATE+TIME', $upload_time) .' ----------------'."\n");

			if ( $station_id != 'no_station_id' ) {
				//Get Company Short name for station_id
				$slf = new StationListFactory();
				$slf->getByStationID( $station_id );
				if ( $slf->getRecordCount() > 0 ) {
					$s_obj = $slf->getCurrent();
					$company_name = $s_obj->getCompanyObject()->getShortName();
				} else {
					$company_name = 'no_company';
				}
				unset($slf, $s_obj);
			} else {
				$company_name = 'no_company';
			}

			$dir = $base_dir . $company_name . DIRECTORY_SEPARATOR;;

			if ( !file_exists($dir) ) {
				mkdir($dir);
			}

			$file_name = $dir.$station_id;

			Debug::Text('Company Name: '. $company_name .' File Name: '. $file_name , __FILE__, __LINE__, __METHOD__,10);

			file_put_contents( $file_name, $line_arr, FILE_APPEND );

			unset($company_name);
		}

		return TRUE;
	}

	function setOfflinePunch( $data ) {
		Debug::Text('Setting Offline Punches... Rows: '. count($data), __FILE__, __LINE__, __METHOD__,10);

		//
		//WHen in Offline mode, default Type/Status to "AUTO"...
		//That way once I get the punches, I can determine what they should be on my end.
		//

		if ( !is_array($data) OR count($data) == 0 ) {
			return FALSE;
		}

		ksort($data);

		//Debug::Arr($data, 'offlinePunchDataArr', __FILE__, __LINE__, __METHOD__,10);

/*
		//Original
		$data[] = array(
						'user_id' => 1,
						'time_stamp' => '12:00 PM',
						'date_stamp' => '03-Dec-05',
						'branch_id' => 1,
						'department_id' => NULL,
						'status_id' => 20,
						'type_id' => 20,
						'punch_control_id' => 0,
						'station_id' => '7D00000023352A81'
						);
*/
/*
		unset($data);

		$data[] = array(
						'user_id' => 1001,
						'time_stamp' => '08:00 AM',
						'date_stamp' => '05-Dec-05',
						'branch_id' => 5,
						'department_id' => 3,
						'status_id' => 0,
						'type_id' => 0,
						'punch_control_id' => 0,
						'station_id' => '7D00000023352A81'
						);

		$data[] = array(
						'user_id' => 1001,
						'time_stamp' => '12:00 PM',
						'date_stamp' => '05-Dec-05',
						'branch_id' => 0,
						'department_id' => 3,
						'status_id' => 20,
						'type_id' => 0,
						'punch_control_id' => 0,
						'station_id' => '7D00000023352A81'
						);
*/
/*
		$data[] = array(
						'user_id' => 1001,
						'time_stamp' => '1:00 PM',
						'date_stamp' => '05-Dec-05',
						'branch_id' => 6,
						'department_id' => 0,
						'status_id' => 0,
						'type_id' => 20,
						'punch_control_id' => 0,
						'station_id' => '7D00000023352A81'
						);
*/
/*
		$data[] = array(
						'user_id' => 1001,
						'time_stamp' => '5:00 PM',
						'date_stamp' => '05-Dec-05',
						'branch_id' => 0,
						'department_id' => 0,
						'status_id' => 0,
						'type_id' => 0,
						'punch_control_id' => 0,
						'station_id' => '7D00000023352A81'
						);
*/
		Debug::Arr($data, 'offlinePunchDataArr', __FILE__, __LINE__, __METHOD__,10);


		//One punch per row
		foreach( $data as $row_key => $punch_row ) {

			Debug::Text('--------------------------========================---------------------------', __FILE__, __LINE__, __METHOD__,10);
			Debug::Text('--------------------------========================---------------------------', __FILE__, __LINE__, __METHOD__,10);

			Debug::Text('Row Key: '. $row_key .' Time: '. $punch_row['time_stamp'], __FILE__, __LINE__, __METHOD__,10);

			if ( isset( $punch_row['station_id']) )  {
				$slf = new StationListFactory();
				$slf->getByStationId( $punch_row['station_id'] );
				if ( $slf->getRecordCount() > 0 ) {
					Debug::Text('Found Station Data...', __FILE__, __LINE__, __METHOD__,10);
					$current_station = $slf->getCurrent();
				} else {
					Debug::Text('DID NOT Find Station Data...', __FILE__, __LINE__, __METHOD__,10);
					continue;
				}
				unset($slf);
			}

			if ( isset( $punch_row['user_id'] ) AND $punch_row['user_id'] != '' ) {
				$ulf = new UserListFactory();
				$ulf->getById( $punch_row['user_id'] );
				if ( $ulf->getRecordCount() > 0 ) {
					$current_user = $ulf->getCurrent();
					Debug::Text('Valid User ID: '. $punch_row['user_id'] .' User Name: '. $current_user->getFullName(), __FILE__, __LINE__, __METHOD__,10);

					//Need to handle timezone somehow. The station should send us the system's timezone
					//so we can calculate based on that.
					//Or just use the employees date preference.
					$current_user->getUserPreferenceObject()->setDateTimePreferences();
				} else {
					Debug::Text('aInValid User ID: '. $punch_row['user_id'], __FILE__, __LINE__, __METHOD__,10);
					continue;
				}
			} else {
				Debug::Text('bInValid User ID: '. $punch_row['user_id'], __FILE__, __LINE__, __METHOD__,10);
				continue;
			}

			$pcf = new PunchControlFactory();
			$pf = new PunchFactory();
			$slf = new ScheduleListFactory();

			//FIXME: If we start trans here, the count is off when a duplicate punch comes in
			//So the transaction is never committed...
			//Transactions seem to work fine otherwise though.
			//$pf->StartTransaction();

			$punch_full_time_stamp = TTDate::strtotime( $punch_row['date_stamp'].' '.$punch_row['time_stamp'] );
			//Make sure time stamp converts properly, otherwise skip this punch.
			if ( !is_int($punch_full_time_stamp) ) {
				Debug::Text('Failed TimeStamp: '. $punch_full_time_stamp, __FILE__, __LINE__, __METHOD__,10);
				continue;
			}

			/*
			//As of version 1.5.1 the offset is pre-applied and displayed in the punch window.
			//It sends the offset in with each punch, but it is ignored.
			if ( isset($punch_row['offset']) ) {
				Debug::Text('Date/Time Offset: '. $punch_row['offset'], __FILE__, __LINE__, __METHOD__,10);
				$punch_full_time_stamp = $punch_full_time_stamp - $punch_row['offset'];
			}
			*/
			Debug::Text('Punch Date/Time: '. $punch_full_time_stamp .' Offset that was already applied: '. $punch_row['offset'], __FILE__, __LINE__, __METHOD__,10);

			//Auto Punch
			if ( ( isset($punch_row['status_id']) AND $punch_row['status_id'] == 0 )
					OR ( isset($punch_row['type_id']) AND $punch_row['type_id'] == 0 )
					OR ( isset($punch_row['branch_id']) AND $punch_row['branch_id'] == 0 )
					OR ( isset($punch_row['department_id']) AND $punch_row['department_id'] == 0 )
					OR ( isset($punch_row['job_id']) AND $punch_row['job_id'] == 0 )
					OR ( isset($punch_row['job_item_id']) AND $punch_row['job_item_id'] == 0 )
					) {

				$plf = new PunchListFactory();
				$plf->getPreviousPunchByUserIDAndEpoch( $punch_row['user_id'], $punch_full_time_stamp );
				if ($plf->getRecordCount() > 0 ) {
					Debug::Text(' Found Previous Punch within Continuous Time from now: ', __FILE__, __LINE__, __METHOD__,10);
					$prev_punch_obj = $plf->getCurrent();

					$branch_id = $prev_punch_obj->getPunchControlObject()->getBranch();
					$department_id = $prev_punch_obj->getPunchControlObject()->getDepartment();
					$job_id = $prev_punch_obj->getPunchControlObject()->getJob();
					$job_item_id = $prev_punch_obj->getPunchControlObject()->getJobItem();
					$quantity = $prev_punch_obj->getPunchControlObject()->getQuantity();
					$bad_quantity = $prev_punch_obj->getPunchControlObject()->getBadQuantity();

					if ( $branch_id == '' OR empty($branch_id) OR $department_id == '' OR empty($department_id) ) {
						Debug::Text(' Branch or department are null. ', __FILE__, __LINE__, __METHOD__,10);

						$s_obj = $slf->getScheduleObjectByUserIdAndEpoch( $punch_row['user_id'], $punch_full_time_stamp );

						if ( is_object($s_obj) ) {
							Debug::Text(' Found Schedule!: ', __FILE__, __LINE__, __METHOD__,10);

							if ( $branch_id == '' OR empty($branch_id) ) {
								Debug::Text(' overrriding branch: '. $s_obj->getBranch(), __FILE__, __LINE__, __METHOD__,10);
								$branch_id = $s_obj->getBranch();
							}
							if ( $department_id == '' OR empty($department_id) ) {
								Debug::Text(' overrriding department: '. $s_obj->getDepartment(), __FILE__, __LINE__, __METHOD__,10);
								$department_id = $s_obj->getDepartment();
							}
						}
					}

					$type_id = $prev_punch_obj->getNextType();
					$status_id = $prev_punch_obj->getNextStatus();

					//CHeck for meal policy window.
					$prev_punch_obj->setScheduleID( $punch_full_time_stamp );
					if ( is_object( $prev_punch_obj->getScheduleObject() )
							AND is_object($prev_punch_obj->getScheduleObject()->getSchedulePolicyObject() )
							AND is_object($prev_punch_obj->getScheduleObject()->getSchedulePolicyObject()->getMealPolicyObject() )
							AND $prev_punch_obj->getType() != 20 ) {
						Debug::Text(' Found Schedule Meal Policy Object: Start Window: '. $prev_punch_obj->getScheduleObject()->getSchedulePolicyObject()->getMealPolicyObject()->getStartWindow(), __FILE__, __LINE__, __METHOD__,10);

						if ( $punch_full_time_stamp >= ($prev_punch_obj->getScheduleObject()->getStartTime() + $prev_punch_obj->getScheduleObject()->getSchedulePolicyObject()->getMealPolicyObject()->getStartWindow() )
								AND $punch_full_time_stamp <= ($prev_punch_obj->getScheduleObject()->getStartTime() + $prev_punch_obj->getScheduleObject()->getSchedulePolicyObject()->getMealPolicyObject()->getStartWindow() + $prev_punch_obj->getScheduleObject()->getSchedulePolicyObject()->getMealPolicyObject()->getWindowLength() ) ) {
							Debug::Text(' Setting Type to Lunch: ', __FILE__, __LINE__, __METHOD__,10);
							$type_id = 20;
						}
					} elseif ( is_object($prev_punch_obj) AND $prev_punch_obj->getType() != 20 ) {
						//Check NON-scheduled meal policies
						$mplf = new MealPolicyListFactory();
						$mplf->getByPolicyGroupUserId( $punch_row['user_id'] );
						if ( $mplf->getRecordCount() > 0 ) {
							$mp_obj = $mplf->getCurrent();
							Debug::Text(' Found NON Schedule Meal Policy start Window: '. $mp_obj->getStartWindow(), __FILE__, __LINE__, __METHOD__,10);

							if ( $punch_full_time_stamp >= ($prev_punch_obj->getTimeStamp() + $mp_obj->getStartWindow())
									AND $punch_full_time_stamp <= ($prev_punch_obj->getTimeStamp() + $mp_obj->getStartWindow() + $mp_obj->getWindowLength() ) ) {
								Debug::Text(' Setting Type to Lunch: ', __FILE__, __LINE__, __METHOD__,10);
								$type_id = 20;
							}
						} else {
							Debug::Text(' DID NOT Find NON Schedule Meal Policy start Window: ', __FILE__, __LINE__, __METHOD__,10);
						}
						unset($mplf, $mp_obj);
					}
				} else {
					Debug::Text(' DID NOT Find Previous Punch within Continuous Time from now: ', __FILE__, __LINE__, __METHOD__,10);
					$branch_id = NULL;
					$department_id = NULL;
					$job_id = NULL;
					$job_item_id = NULL;

					$s_obj = $slf->getScheduleObjectByUserIdAndEpoch( $punch_row['user_id'], $punch_full_time_stamp );
					if ( is_object($s_obj) ) {
						Debug::Text(' Found Schedule!: ', __FILE__, __LINE__, __METHOD__,10);
						$branch_id = $s_obj->getBranch();
						$department_id = $s_obj->getDepartment();
					} else {
						$branch_id = $current_user->getDefaultBranch();
						$department_id = $current_user->getDefaultDepartment();
					}

					$status_id = 10; //In
					$type_id = 10; //Normal
				}

				if ( isset($punch_row['status_id']) AND $punch_row['status_id'] != 0 ) {
					Debug::Text(' Status ID is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$status_id = $punch_row['status_id'];
				}

				if ( isset($punch_row['type_id']) AND $punch_row['type_id'] != 0 ) {
					Debug::Text(' Type ID is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$type_id = $punch_row['type_id'];
				}

				if ( isset($punch_row['branch_id']) AND $punch_row['branch_id'] != 0 ) {
					Debug::Text(' Branch ID is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$branch_id = $punch_row['branch_id'];
				}

				if ( isset($punch_row['department_id']) AND $punch_row['department_id'] != 0 ) {
					Debug::Text(' Department ID is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$department_id = $punch_row['department_id'];
				}

				if ( isset($punch_row['job_id']) AND $punch_row['job_id'] != 0 ) {
					Debug::Text(' Job ID is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$job_id = $punch_row['job_id'];
				}

				if ( isset($punch_row['job_item_id']) AND $punch_row['job_item_id'] != 0 ) {
					Debug::Text(' Job Item ID is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$job_item_id = $punch_row['job_item_id'];
				}

				if ( isset($punch_row['quantity']) ) {
					Debug::Text(' Quantity is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$quantity = $punch_row['quantity'];
				}

				if ( isset($punch_row['bad_quantity']) ) {
					Debug::Text(' Bad Quantity is NOT AUTO!', __FILE__, __LINE__, __METHOD__,10);
					$bad_quantity = $punch_row['bad_quantity'];
				}

			} else {
				$status_id = $punch_row['status_id'];
				$type_id = $punch_row['type_id'];
				$branch_id = $punch_row['branch_id'];
				$department_id = $punch_row['department_id'];
				$job_id = $punch_row['job_id'];
				$job_item_id = $punch_row['job_item_id'];
				$quantity = $punch_row['quantity'];
				$bad_quantity = $punch_row['bad_quantity'];
			}

			//Save Punch Control first
			if ( isset($status_id) AND $status_id == 20 ) { //Out
				if ( isset($punch_row['punch_control_id'])
						AND $punch_row['punch_control_id'] != ''
						AND $punch_row['punch_control_id'] != 0 ) {
					Debug::Text(' Using Passed Punch Control ID: '. $punch_row['punch_control_id'], __FILE__, __LINE__, __METHOD__,10);
					$pcf->setId( $punch_row['punch_control_id'] );
				} else {
					Debug::Text(' Checking for Previous Punch... User ID: '. $punch_row['user_id'] .' TimeStamp: '. $punch_full_time_stamp, __FILE__, __LINE__, __METHOD__,10);
					$plf = new PunchListFactory();
					$plf->getPreviousPunchByUserIDAndEpoch( $punch_row['user_id'], $punch_full_time_stamp );
					if ($plf->getRecordCount() > 0 ) {
						Debug::Text(' Found Previous Punch within Continuous Time from now: ', __FILE__, __LINE__, __METHOD__,10);
						$prev_punch_obj = $plf->getCurrent();

						$pcf->setId( $prev_punch_obj->getPunchControlId() );

					} else {
						Debug::Text(' Did not find previous punch!! BAD!...', __FILE__, __LINE__, __METHOD__,10);
					}
				}
			} else {
				$status_id = 10; // In
			}

			if ( !isset($punch_row['user_date_id'] )
					OR $punch_row['user_date_id'] == ''
					OR $punch_row['user_date_id'] == 0 ) {
				$pcf->findUserDate( $punch_row['user_id'], $punch_full_time_stamp, $status_id );
			} else {
				$pcf->setUserDateID( $punch_row['user_date_id'] );
			}

			if ( isset($branch_id) AND $branch_id != '') {
				$pcf->setBranch( $branch_id );
			}
			if ( isset($department_id) AND $department_id != '' ) {
				$pcf->setDepartment( $department_id );
			}

			if ( isset($job_id) AND $job_id != '' ) {
				$pcf->setJob( $job_id );
			}
			if ( isset($job_item_id) AND $job_item_id != '') {
				$pcf->setJobItem( $job_item_id );
			}
			if ( isset($quantity) AND $quantity != '' ) {
				$pcf->setQuantity( $quantity );
			}
			if ( isset($bad_quantity) AND $bad_quantity != '' ) {
				$pcf->setBadQuantity( $bad_quantity );
			}

			if ( isset($punch_row['note']) AND $punch_row['note'] != '' ) {
				$pcf->setNote( $punch_row['note'] );
			}

			if ( isset($punch_row['other_id1']) AND $punch_row['other_id1'] != '' ) {
				$pcf->setOtherID1( $punch_row['other_id1'] );
			}
			if ( isset($punch_row['other_id2']) AND $punch_row['other_id2'] != '' ) {
				$pcf->setOtherID2( $punch_row['other_id2'] );
			}
			if ( isset($punch_row['other_id3']) AND $punch_row['other_id3'] != '' ) {
				$pcf->setOtherID3( $punch_row['other_id3'] );
			}
			if ( isset($punch_row['other_id4']) AND $punch_row['other_id4'] != '' ) {
				$pcf->setOtherID4( $punch_row['other_id4'] );
			}
			if ( isset($punch_row['other_id5']) AND $punch_row['other_id5'] != ''  ) {
				$pcf->setOtherID5( $punch_row['other_id5'] );
			}

			if ( $pcf->isValid() ) {
				$punch_control_id = $pcf->Save();

				//If its an update, not a new insert
				if ( $punch_control_id === TRUE ) {
					Debug::Text(' Updating Punch Control Object', __FILE__, __LINE__, __METHOD__,10);

					if ( isset($punch_row['punch_control_id']) AND $punch_row['punch_control_id'] != '' ) {
						Debug::Text(' Using passed Punch Control ID...', __FILE__, __LINE__, __METHOD__,10);
						$punch_control_id = $punch_row['punch_control_id'];
					} elseif ( isset($prev_punch_obj) ) {
						Debug::Text(' Using last Punch Control ID...', __FILE__, __LINE__, __METHOD__,10);
						$punch_control_id = $prev_punch_obj->getPunchControlID();
					} else {
						Debug::Text(' Not Setting Punch Control ID, BAD!...', __FILE__, __LINE__, __METHOD__,10);
					}
				}
				Debug::Text(' Punch Control ID: '. $punch_control_id, __FILE__, __LINE__, __METHOD__,10);

				if ( isset($punch_row['transfer']) AND $punch_row['transfer'] == 1 ) {
					Debug::Text(' Enabling Transfer!: ', __FILE__, __LINE__, __METHOD__,10);
					$pf->setTransfer( TRUE );
				}

				$pf->setPunchControlID( $punch_control_id );

				$pf->setType( $type_id );
				$pf->setStatus( $status_id );
				$pf->setTimeStamp( $punch_full_time_stamp, TRUE ); //Make sure we round here.

				if ( $pf->isNew() ) {
					Debug::Text(' Setting Actual TimeStamp!: ', __FILE__, __LINE__, __METHOD__,10);
					$pf->setActualTimeStamp( $punch_full_time_stamp );
					$pf->setOriginalTimeStamp( $pf->getTimeStamp() );
				}

				$pf->setStation( $current_station->getId() );

				if ( $pf->isValid() ) {
					$return_date = $pf->getTimeStamp();

					$pf->setEnableCalcTotalTime( TRUE );
					$pf->setEnableCalcSystemTotalTime( TRUE );
					$pf->setEnableCalcUserDateTotal( TRUE );
					//Because punches can be older then one day, we have to do this
					//FIXME: queue up which days to calc exceptions on and run that later.
					$pf->setEnableCalcException( TRUE );

					if ( $pf->Save() == TRUE ) {
						Debug::text('Saved Punch!', __FILE__, __LINE__, __METHOD__, 10);
						//$pf->CommitTransaction();
					} else {
						Debug::text('Save failed... Failing Transaction!', __FILE__, __LINE__, __METHOD__, 10);
						///$pf->FailTransaction();
					}

				} else {
					Debug::text('Punch is NOT VALID... Failing Transaction ', __FILE__, __LINE__, __METHOD__, 10);
					//$pf->FailTransaction();
				}

			} else {
				Debug::text('bFailing Transaction!', __FILE__, __LINE__, __METHOD__, 10);
				//$pf->FailTransaction();
			}

			//Fail all for now.
			//$pf->FailTransaction();

			unset($punch_full_time_stamp, $current_station, $current_user);
			//End Foreach
		}

		return TRUE;
		//return FALSE;
	}
}
?>
