<?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: 2453 $
 * $Id: Data.class.php 2453 2009-03-20 16:34:04Z ipso $
 * $Date: 2009-03-20 09:34:04 -0700 (Fri, 20 Mar 2009) $
 */

/**
 * @package PayrollDeduction
 */

/**
 * @package PayrollDeduction
 */
class PayrollDeduction_CA_Data extends PayrollDeduction_Base {
	var $db = NULL;
	var $income_tax_rates = array();
	var $table = 'income_tax_rate';
	var $country_primary_currency = 'CAD';

	/*
		Claim Code Basic Amounts
	*/

	var $basic_claim_code_options = array(
							1238569200 => array( //01-Apr-09
										'CA' => 10375, //Federal
										'BC' => 9373,
										'AB' => 16775,
										'SK' => 13269,
										'MB' => 8134,
										'QC' => 0,
										'ON' => 8881,
										'NF' => 7778,
										'NB' => 8134,
										'NS' => 7981,
										'PE' => 7708,
										'NT' => 12664,
										'YU' => 10375,
										'NU' => 11644,
										),
							1230796800 => array( //01-Jan-09
										'CA' => 10100, //Federal
										'BC' => 9373,
										'AB' => 16775,
										'SK' => 13269,
										'MB' => 8134,
										'QC' => 0,
										'ON' => 8881,
										'NF' => 7778,
										'NB' => 8134,
										'NS' => 7981,
										'PE' => 7708,
										'NT' => 12664,
										'YU' => 10100,
										'NU' => 11644,
										),
							1199174400 => array( //01-Jan-08
										'CA' => 9600, //Federal
										'BC' => 9189,
										'AB' => 16161,
										'SK' => 8945,
										'MB' => 8034,
										'QC' => 0,
										'ON' => 8681,
										'NF' => 7566,
										'NB' => 8395,
										'NS' => 7731,
										'PE' => 7708,
										'NT' => 12355,
										'YU' => 9600,
										'NU' => 11360,
										),
							1183273200 => array( //01-Jul-07
										'CA' => 8929, //Federal
										'BC' => 9027,
										'AB' => 15435,
										'SK' => 8778,
										'MB' => 7834,
										'QC' => 0,
										'ON' => 8553,
										'NF' => 7558,
										'NB' => 8239,
										'NS' => 7481,
										'PE' => 7708,
										'NT' => 12125,
										'YU' => 8929,
										'NU' => 11149,
										),
							1167638400 => array( //01-Jan-07
										'CA' => 8929, //Federal
										'BC' => 9027,
										'AB' => 15435,
										'SK' => 8778,
										'MB' => 7834,
										'QC' => 0,
										'ON' => 8553,
										'NF' => 7410,
										'NB' => 8239,
										'NS' => 7481,
										'PE' => 7412,
										'NT' => 12125,
										'YU' => 8929,
										'NU' => 11149,
										),
							1151737200 => array( //01-Jul-06
										'CA' => 8639, //Federal
										'BC' => 8858,
										'AB' => 14999,
										'SK' => 8589,
										'MB' => 7734,
										'QC' => 0,
										'ON' => 8377,
										'NF' => 7410,
										'NB' => 8061,
										'NS' => 7231,
										'PE' => 7412,
										'NT' => 11864,
										'YU' => 8328,
										'NU' => 10909,
										),
							1136102400 => array( //01-Jan-06
										'CA' => 9039, //Federal
										'BC' => 8858,
										'AB' => 14799,
										'SK' => 8589,
										'MB' => 7734,
										'QC' => 0,
										'ON' => 8377,
										'NF' => 7410,
										'NB' => 8061,
										'NS' => 7231,
										'PE' => 7412,
										'NT' => 11864,
										'YU' => 8328,
										'NU' => 10909,
										),
									);

	/*
		CPP settings
	*/
	var $cpp_options = array(
							1230796800 => array( //2009
										'maximum_pensionable_earnings' => 46300,
										'basic_exemption' => 3500,
										'employee_rate' => 0.0495,
										'employee_maximum_contribution' => 2118.60
										),
							1199174400 => array( //2008
										'maximum_pensionable_earnings' => 44900,
										'basic_exemption' => 3500,
										'employee_rate' => 0.0495,
										'employee_maximum_contribution' => 2049.30
										),
							1167638400 => array( //2007
										'maximum_pensionable_earnings' => 43700,
										'basic_exemption' => 3500,
										'employee_rate' => 0.0495,
										'employee_maximum_contribution' => 1989.90
										),
							1136102400 => array( //2006
										'maximum_pensionable_earnings' => 42100,
										'basic_exemption' => 3500,
										'employee_rate' => 0.0495,
										'employee_maximum_contribution' => 1910.70
										),
							1104566400 => array( //2005
										'maximum_pensionable_earnings' => 41100,
										'basic_exemption' => 3500,
										'employee_rate' => 0.0495,
										'employee_maximum_contribution' => 1861.20
										),
							1072944000 => array( //2004
										'maximum_pensionable_earnings' => 40500,
										'basic_exemption' => 3500,
										'employee_rate' => 0.0495,
										'employee_maximum_contribution' => 1831.50
										),
							);

	/*
		EI settings
	*/
	var $ei_options = array(
							1230796800 => array( //2009
										'maximum_insurable_earnings' => 42300,
										'employee_rate' => 0.0173,
										'employee_maximum_contribution' => 731.79,
										'employer_rate' => 1.4
										),
							1199174400 => array( //2008
										'maximum_insurable_earnings' => 41100,
										'employee_rate' => 0.0173,
										'employee_maximum_contribution' => 711.03,
										'employer_rate' => 1.4
										),
							1167638400 => array( //2007
										'maximum_insurable_earnings' => 40000,
										'employee_rate' => 0.0180,
										'employee_maximum_contribution' => 720.00,
										'employer_rate' => 1.4
										),
							1136102400 => array( //2006
										'maximum_insurable_earnings' => 39000,
										'employee_rate' => 0.0187,
										'employee_maximum_contribution' => 729.30,
										'employer_rate' => 1.4
										),
							1104566400 => array( //2005
										'maximum_insurable_earnings' => 39000,
										'employee_rate' => 0.0195,
										'employee_maximum_contribution' => 760.50,
										'employer_rate' => 1.4
										),
							1072944000 => array( //2004
										'maximum_insurable_earnings' => 39900,
										'employee_rate' => 0.0198,
										'employee_maximum_contribution' => 722.20,
										'employer_rate' => 1.4
										),
							);

	function __construct() {
		global $db;

		$this->db = $db;

		return TRUE;
	}

	/*
		Claim Code Functions
	*/
	function getBasicClaimCodeData( $date ) {
		foreach( $this->basic_claim_code_options as $effective_date => $data ) {
			if ( $date >= $effective_date ) {
				return $data;
			}
		}

		return FALSE;
	}
	function getBasicFederalClaimCodeAmount() {
		$data = $this->getBasicClaimCodeData( $this->getDate() );

		if ( isset($data['CA']) ) {
			return $data['CA'];
		}

		return FALSE;
	}

	function getBasicProvinceClaimCodeAmount() {
		$data = $this->getBasicClaimCodeData( $this->getDate() );

		if ( isset($data[$this->getProvince()]) ) {
			return $data[$this->getProvince()];
		}

		return FALSE;
	}

	/*
		CPP functions
	*/
	function getCPPData( $date ) {
		foreach( $this->cpp_options as $effective_date => $data ) {
			if ( $date >= $effective_date ) {
				return $data;
			}
		}

		return FALSE;
	}

	function getCPPMaximumEarnings() {
		$data = $this->getCPPData( $this->getDate() );

		return $data['maximum_pensionable_earnings'];
	}

	function getCPPBasicExemption() {
		$data = $this->getCPPData( $this->getDate() );

		return $data['basic_exemption'];
	}

	function getCPPEmployeeRate() {
		$data = $this->getCPPData( $this->getDate() );

		Debug::text('Date: '. $this->getDate() .' Rate: '. $data['employee_rate'], __FILE__, __LINE__, __METHOD__,10);
		return $data['employee_rate'];
	}

	function getCPPEmployeeMaximumContribution() {
		$data = $this->getCPPData( $this->getDate() );

		return $data['employee_maximum_contribution'];
	}

	/*
		EI functions
	*/
	function getEIData( $date ) {
		foreach( $this->ei_options as $effective_date => $data ) {
			if ( $date >= $effective_date ) {
				return $data;
			}
		}

		return FALSE;
	}
	function getEIMaximumEarnings() {
		$data = $this->getEIData( $this->getDate() );

		return $data['maximum_insurable_earnings'];
	}

	function getEIEmployeeRate() {
		$data = $this->getEIData( $this->getDate() );

		return $data['employee_rate'];
	}

	function getEIEmployeeMaximumContribution() {
		$data = $this->getEIData( $this->getDate() );

		return $data['employee_maximum_contribution'];
	}

	function getEIEmployerRate() {
		$data = $this->getEIData( $this->getDate() );

		return $data['employer_rate'];
	}

	function getData() {
		global $cache;

		$country = $this->getCountry();
		$province = $this->getProvince();
		$epoch = $this->getDate();

		if ($epoch == NULL OR $epoch == ''){
			//$year = date('Y');
			$epoch = TTDate::getTime();
		}

		Debug::text('bUsing ('. $province .') values from: '. TTDate::getDate('DATE+TIME', $epoch) , __FILE__, __LINE__, __METHOD__,10);

		$cache_id = $country.$province.$epoch;

		if ( is_string( $cache->get($cache_id, $this->table ) ) ) {
			$this->income_tax_rates = unserialize( $cache->get($cache_id, $this->table ) );
			Debug::text('Using Cached Income Tax Data!', __FILE__, __LINE__, __METHOD__,10);
		} else {
			$this->income_tax_rates = FALSE;
		}


		if ( $this->income_tax_rates === FALSE ) {
			//There were issues with this query when provincial taxes were updated but not federal
			//We need to basically make a union query that queries the latest federal taxes separate
			//from the provincial
			$query = 'select country,province,income,rate,constant,effective_date
						from '. $this->table .'
						where
								(
								effective_date = ( 	select effective_date
													from '. $this->table .'
													where effective_date <= '. $epoch .'
														AND country = '. $this->db->qstr($country).'
														AND province is NULL
													ORDER BY effective_date DESC
													LIMIT 1)
								)
							AND
							( country = '. $this->db->qstr($country).'
									and province is NULL)
							OR
								(
								effective_date = ( 	select effective_date
													from '. $this->table .'
													where effective_date <= '. $epoch .'
														AND country = '. $this->db->qstr($country).'
														AND province = '. $this->db->qstr($province) .'
													ORDER BY effective_date DESC
													LIMIT 1)
								)
							AND
							( country = '. $this->db->qstr($country).'
									and province = '. $this->db->qstr($province) .')
						ORDER BY province desc, income asc, rate asc
					';
			//Debug::text('Query: '. $query , __FILE__, __LINE__, __METHOD__,10);
			try {
				$rs = $this->db->Execute($query);
			} catch (Exception $e) {
				throw new DBError($e);
			}

			$rs = $rs->GetRows();

			foreach($rs as $key => $arr) {
				if ( $arr['province'] == NULL ) {
					$type = 'federal';
				} else {
					$type = 'provincial';
				}

				$this->income_tax_rates[$type][] = array('income' => trim($arr['income']), 'rate' => ( bcdiv( trim($arr['rate']), 100 ) ), 'constant' => trim($arr['constant']) );
			}
			Debug::text('bUsing values from: '. TTDate::getDate('DATE+TIME', $arr['effective_date']) , __FILE__, __LINE__, __METHOD__,10);

			//var_dump($this->income_tax_rates);
			$cache->save(serialize($this->income_tax_rates), $cache_id, $this->table );
		}

		return $this;
	}

	private function getRateArray($income, $type) {
		Debug::text('Calculating '. $type .' Taxes on: $'. $income, __FILE__, __LINE__, __METHOD__,10);

		if ( isset($this->income_tax_rates[$type]) ) {
			$rates = $this->income_tax_rates[$type];
		} else {
			Debug::text('aNO INCOME TAX RATES FOUND!!!!!! '. $type .' Taxes on: $'. $income, __FILE__, __LINE__, __METHOD__,10);
			return FALSE;
		}

		if ( count($rates) == 0 ) {
			Debug::text('bNO INCOME TAX RATES FOUND!!!!!! '. $type .' Taxes on: $'. $income, __FILE__, __LINE__, __METHOD__,10);
			return FALSE;
		}

		$prev_value = 0;
		$total_rates = count($rates) - 1;
		$i=0;
		foreach ($rates as $key => $values) {
			$value = $values['income'];
			$rate = $values['rate'];
			$constant = $values['constant'];

			Debug::text('Value: '. $value .' Rate: '. $rate .' Constant: '. $constant .' Previous Value: '. $prev_value , __FILE__, __LINE__, __METHOD__,10);

			if ($income > $prev_value AND $income <= $value) {
				Debug::text('Found Key: '. $key, __FILE__, __LINE__, __METHOD__,10);

				return $this->income_tax_rates[$type][$key];
			} elseif ($i == $total_rates) {
				Debug::text('Found Last Key: '. $key, __FILE__, __LINE__, __METHOD__,10);
				return $this->income_tax_rates[$type][$key];
			}

			$prev_value = $value;
			$i++;
		}

		return FALSE;
	}

	function getFederalLowestRate() {
		$arr = $this->getRateArray(1, 'federal');
		Debug::text('Federal Lowest Rate: '. $arr['rate'], __FILE__, __LINE__, __METHOD__,10);
		return $arr['rate'];
	}

	function getFederalRate($income) {
		$arr = $this->getRateArray($income, 'federal');
		Debug::text('Federal Rate: '. $arr['rate'], __FILE__, __LINE__, __METHOD__,10);
		return $arr['rate'];
	}

	function getFederalConstant($income) {
		$arr = $this->getRateArray($income, 'federal');
		Debug::text('Federal Constant: '. $arr['constant'], __FILE__, __LINE__, __METHOD__,10);
		return $arr['constant'];
	}

	function getProvincialLowestRate() {
		$arr = $this->getRateArray(1, 'provincial');
		Debug::text('Provincial Lowest Rate: '. $arr['rate'], __FILE__, __LINE__, __METHOD__,10);
		return $arr['rate'];
	}

	function getProvincialRate($income) {
		$arr = $this->getRateArray($income, 'provincial');
		Debug::text('Provincial Rate: '. $arr['rate'], __FILE__, __LINE__, __METHOD__,10);
		return $arr['rate'];
	}

	function getProvincialConstant($income) {
		$arr = $this->getRateArray($income, 'provincial');
		Debug::text('Provincial Constant: '. $arr['constant'], __FILE__, __LINE__, __METHOD__,10);
		return $arr['constant'];
	}

	function test3() {
		Debug::text('Sub-Class Test3: '. __CLASS__ , __FILE__, __LINE__, __METHOD__, 10);
		return 'blah3';
	}
}
?>
