function testCA_2013a_Example4()
 {
     Debug::text('CA - Example1 - Beginning of 01-Jan-2013: ', __FILE__, __LINE__, __METHOD__, 10);
     $pd_obj = new PayrollDeduction('CA', 'BC');
     $pd_obj->setDate(strtotime('01-Jan-2013'));
     $pd_obj->setEnableCPPAndEIDeduction(TRUE);
     //Deduct CPP/EI.
     $pd_obj->setAnnualPayPeriods(26);
     $pd_obj->setFederalTotalClaimAmount(11038);
     $pd_obj->setProvincialTotalClaimAmount(10276);
     $pd_obj->setWCBRate(0);
     $pd_obj->setEIExempt(FALSE);
     $pd_obj->setCPPExempt(FALSE);
     $pd_obj->setFederalTaxExempt(FALSE);
     $pd_obj->setProvincialTaxExempt(FALSE);
     $pd_obj->setYearToDateCPPContribution(0);
     $pd_obj->setYearToDateEIContribution(0);
     $pd_obj->setGrossPayPeriodIncome(1560);
     $this->assertEquals($this->mf($pd_obj->getGrossPayPeriodIncome()), '1560');
     $this->assertEquals($this->mf($pd_obj->getFederalPayPeriodDeductions()), '148.89');
     $this->assertEquals($this->mf($pd_obj->getProvincialPayPeriodDeductions()), '56.91');
 }
 function testCA_2006a_MAXEI_LowIncome()
 {
     Debug::text('CA - MAXEI - Beginning of 2006 01-Jan-06: ', __FILE__, __LINE__, __METHOD__, 10);
     $pd_obj = new PayrollDeduction('CA', 'BC');
     $pd_obj->setDate(strtotime('01-Jan-06'));
     $pd_obj->setEnableCPPAndEIDeduction(TRUE);
     //Deduct CPP/EI.
     $pd_obj->setAnnualPayPeriods(26);
     $pd_obj->setFederalTotalClaimAmount(9039);
     $pd_obj->setProvincialTotalClaimAmount(0);
     $pd_obj->setWCBRate(0.18);
     $pd_obj->setEIExempt(FALSE);
     $pd_obj->setCPPExempt(FALSE);
     $pd_obj->setFederalTaxExempt(FALSE);
     $pd_obj->setProvincialTaxExempt(FALSE);
     $pd_obj->setYearToDateCPPContribution(0);
     $pd_obj->setYearToDateEIContribution(728.3);
     //729.30 - 1.00
     $pd_obj->setGrossPayPeriodIncome(587.0);
     //var_dump($pd_obj->getArray());
     $this->assertEquals($this->mf($pd_obj->getGrossPayPeriodIncome()), '587.00');
     $this->assertEquals($this->mf($pd_obj->getEmployeeEI()), '1.00');
     $this->assertEquals($this->mf($pd_obj->getEmployerEI()), '1.40');
 }
         }
         foreach ($test_data[$country][$province_code]['provincial_claim'] as $provincial_claim) {
             foreach ($test_data[$country][$province_code]['federal_claim'] as $federal_claim) {
                 foreach ($test_data[$country][$province_code]['income'] as $income) {
                     $pd_obj = new PayrollDeduction($country, $province_code);
                     $pd_obj->setDate($effective_date);
                     $pd_obj->setAnnualPayPeriods($pay_periods);
                     $pd_obj->setEnableCPPAndEIDeduction(TRUE);
                     //Deduct CPP/EI.
                     $pd_obj->setFederalTotalClaimAmount($federal_claim);
                     $pd_obj->setProvincialTotalClaimAmount($provincial_claim);
                     $pd_obj->setEIExempt(FALSE);
                     $pd_obj->setCPPExempt(FALSE);
                     $pd_obj->setFederalTaxExempt(FALSE);
                     $pd_obj->setProvincialTaxExempt(FALSE);
                     $pd_obj->setYearToDateCPPContribution(0);
                     $pd_obj->setYearToDateEIContribution(0);
                     $pd_obj->setGrossPayPeriodIncome($income);
                     $retarr[] = array('country' => $country, 'province' => $province_code, 'date' => date('m/d/y', $effective_date), 'pay_periods' => $pay_periods, 'federal_claim' => $pd_obj->getFederalTotalClaimAmount(), 'provincial_claim' => $pd_obj->getProvincialTotalClaimAmount(), 'gross_income' => $income, 'federal_deduction' => Misc::MoneyFormat($pd_obj->getFederalPayPeriodDeductions(), FALSE), 'provincial_deduction' => Misc::MoneyFormat($pd_obj->getProvincialPayPeriodDeductions(), FALSE));
                 }
             }
         }
     }
 }
 //generate column array.
 $column_keys = array_keys($retarr[0]);
 foreach ($column_keys as $column_key) {
     $columns[$column_key] = $column_key;
 }
 //var_dump($test_data);
 //var_dump($retarr);
 function getDeductionAmount($user_id, $pay_stub_obj, $pay_period_obj)
 {
     if ($user_id == '') {
         Debug::Text('Missing User ID: ', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if (!is_object($pay_stub_obj)) {
         Debug::Text('Missing Pay Stub Object: ', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if (!is_object($pay_period_obj)) {
         Debug::Text('Missing Pay Period Object: ', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     //Calculates the deduction.
     $cd_obj = $this->getCompanyDeductionObject();
     $annual_pay_periods = $pay_period_obj->getPayPeriodScheduleObject()->getAnnualPayPeriods();
     if (!is_object($cd_obj)) {
         return FALSE;
     }
     require_once Environment::getBasePath() . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'payroll_deduction' . DIRECTORY_SEPARATOR . 'PayrollDeduction.class.php';
     $retval = 0;
     Debug::Text('Company Deduction: ID: ' . $cd_obj->getID() . ' Name: ' . $cd_obj->getName() . ' Calculation ID: ' . $cd_obj->getCalculation(), __FILE__, __LINE__, __METHOD__, 10);
     switch ($cd_obj->getCalculation()) {
         case 10:
             //Basic Percent
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             $retval = bcmul($amount, bcdiv($percent, 100));
             break;
         case 15:
             //Advanced Percent
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $wage_base = $cd_obj->getUserValue2();
             } else {
                 $wage_base = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $exempt_amount = $cd_obj->getUserValue3();
             } else {
                 $exempt_amount = $this->getUserValue3();
             }
             //Annual Wage Base is the maximum earnings that an employee can earn before they are no longer eligible for this deduction
             //Annual Deduction Amount
             Debug::Text('Percent: ' . $percent . ' Wage Base: ' . $wage_base . ' Exempt Amount: ' . $exempt_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 if ($exempt_amount > 0) {
                     $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), bcdiv($exempt_amount, $annual_pay_periods));
                     Debug::Text('Amount After Exemption: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 } else {
                     $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
                     Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 }
                 if ($wage_base > 0) {
                     //*NOTE: If the first pay stub in TimeTrex is near the end of the year, and the employee has already exceeded the wage base amount
                     //the payroll admin needs to make sure they add a YTD Adjustment for each Include PS Accounts that this calculation is based on,
                     //NOT the total amount they have paid for the resulting calculation, as that has no effect whatsoever.
                     //getCalculationYTDAmount is the previous pay stub YTD amount, but it includes any YTD Adjustments in the current pay stub too.
                     $ytd_amount = $cd_obj->getCalculationYTDAmount($pay_stub_obj);
                     Debug::Text('Wage Base is set: ' . $wage_base . ' Amount: ' . $amount . ' Current YTD: ' . $ytd_amount, __FILE__, __LINE__, __METHOD__, 10);
                     //Possible calcations:
                     //
                     //Wage Base: 3000
                     //Amount: 500 YTD: 0		= 500
                     //Amount: 500 YTD: 2900		= 100
                     //Amount: 500 YTD: 3100		= 0
                     //Amount: 3500 YTD: 0		= 3000
                     //AMount: 3500 YTD: 2900	= 100
                     //Amount: 3500 YTD: 3100	= 0
                     //Check to see if YTD is less than wage base.
                     $remaining_wage_base = bcsub($wage_base, $ytd_amount);
                     Debug::Text('Remaining Wage Base to be calculated: ' . $remaining_wage_base, __FILE__, __LINE__, __METHOD__, 10);
                     if ($remaining_wage_base > 0) {
                         if ($amount > $remaining_wage_base) {
                             $amount = $remaining_wage_base;
                         }
                     } else {
                         $amount = 0;
                         //Exceeded wage base, nothing to calculate.
                     }
                     unset($remaining_wage_base);
                 } else {
                     Debug::Text('Wage Base is NOT set: ' . $wage_base, __FILE__, __LINE__, __METHOD__, 10);
                 }
                 $retval = bcmul($amount, bcdiv($percent, 100));
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $ytd_amount, $percent, $wage_base);
             break;
         case 17:
             //Advanced Percent (Range Bracket)
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $min_wage = $cd_obj->getUserValue2();
             } else {
                 $min_wage = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $max_wage = $cd_obj->getUserValue3();
             } else {
                 $max_wage = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             if ($this->getUserValue5() == '') {
                 $annual_fixed_amount = $cd_obj->getUserValue5();
             } else {
                 $annual_fixed_amount = $this->getUserValue5();
             }
             $min_wage = bcdiv($min_wage, $annual_pay_periods);
             $max_wage = bcdiv($max_wage, $annual_pay_periods);
             $annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
             $annual_fixed_amount = bcdiv($annual_fixed_amount, $annual_pay_periods);
             Debug::Text('Percent: ' . $percent . ' Min Wage: ' . $min_wage . ' Max Wage: ' . $max_wage . ' Annual Deduction: ' . $annual_deduction_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $annual_deduction_amount);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount >= $min_wage and $amount <= $max_wage) {
                     $retval = bcadd(bcmul($amount, bcdiv($percent, 100)), $annual_fixed_amount);
                 }
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $percent, $min_wage, $max_wage, $annual_deduction_amount, $annual_fixed_amount);
             break;
         case 18:
             //Advanced Percent (Tax Bracket)
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $wage_base = $cd_obj->getUserValue2();
             } else {
                 $wage_base = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $exempt_amount = $cd_obj->getUserValue3();
             } else {
                 $exempt_amount = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             Debug::Text('Percent: ' . $percent . ' Wage Base: ' . $wage_base . ' Exempt Amount: ' . $exempt_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 if ($exempt_amount > 0) {
                     $pp_exempt_amount = bcdiv($exempt_amount, $annual_pay_periods);
                 } else {
                     $pp_exempt_amount = 0;
                 }
                 //Debug::Text('PP Exempt Amount: '. $pp_exempt_amount, __FILE__, __LINE__, __METHOD__,10);
                 if ($wage_base > 0) {
                     $pp_wage_base_amount = bcdiv($wage_base, $annual_pay_periods);
                 } else {
                     $pp_wage_base_amount = 0;
                 }
                 if ($annual_deduction_amount > 0) {
                     $pp_annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
                 } else {
                     $pp_annual_deduction_amount = 0;
                 }
                 //Debug::Text('PP Wage Base Base Amount: '. $pp_wage_base_amount, __FILE__, __LINE__, __METHOD__,10);
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $pp_annual_deduction_amount);
                 //Debug::Text('Calculation Pay Stub Amount: '. $cd_obj->getCalculationPayStubAmount( $pay_stub_obj ), __FILE__, __LINE__, __METHOD__,10);
                 if ($pp_wage_base_amount > 0 and $amount > $pp_wage_base_amount) {
                     //Debug::Text('Exceeds Wage Base...'. $amount, __FILE__, __LINE__, __METHOD__,10);
                     $amount = bcsub($pp_wage_base_amount, $pp_exempt_amount);
                 } else {
                     //Debug::Text('Under Wage Base...'. $amount, __FILE__, __LINE__, __METHOD__,10);
                     $amount = bcsub($amount, $pp_exempt_amount);
                 }
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 $retval = bcmul($amount, bcdiv($percent, 100));
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $percent, $wage_base, $pp_wage_base_amount, $pp_exempt_amount, $annual_deduction_amount, $pp_annual_deduction_amount);
             break;
         case 19:
             //Advanced Percent (Tax Bracket Alternate)
             /*
             	This is designed to be used for single line item tax calculations, in that the formula looks like this,
             	where only ONE bracket would be applied to the employee, NOT all:
             	Wage between 0 - 10,000 calculate 10%
             	Wage between 10,001 - 20,000 calculate 15% + $1000 (10% of 10,000 as per above)
             	Wage between 20,001 - 30,000 calculate 20% + $2500 (10% of 10,000 as first bracket, and 15% of 10,000 as per 2nd bracket)
             */
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $min_wage = $cd_obj->getUserValue2();
             } else {
                 $min_wage = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $max_wage = $cd_obj->getUserValue3();
             } else {
                 $max_wage = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             if ($this->getUserValue5() == '') {
                 $annual_fixed_amount = $cd_obj->getUserValue5();
             } else {
                 $annual_fixed_amount = $this->getUserValue5();
             }
             $min_wage = bcdiv($min_wage, $annual_pay_periods);
             $max_wage = bcdiv($max_wage, $annual_pay_periods);
             $annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
             $annual_fixed_amount = bcdiv($annual_fixed_amount, $annual_pay_periods);
             Debug::Text('Percent: ' . $percent . ' Min Wage: ' . $min_wage . ' Max Wage: ' . $max_wage . ' Annual Deduction: ' . $annual_deduction_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $annual_deduction_amount);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount >= $min_wage and $amount <= $max_wage) {
                     $retval = bcadd(bcmul(bcsub($amount, $min_wage), bcdiv($percent, 100)), $annual_fixed_amount);
                 }
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $percent, $min_wage, $max_wage, $annual_deduction_amount, $annual_fixed_amount);
             break;
         case 20:
             //Fixed amount
             if ($this->getUserValue1() == FALSE) {
                 $amount = $cd_obj->getUserValue1();
             } else {
                 $amount = $this->getUserValue1();
             }
             $retval = $amount;
             unset($amount);
             break;
         case 30:
             //Fixed Amount (Range Bracket)
             if ($this->getUserValue1() == '') {
                 $fixed_amount = $cd_obj->getUserValue1();
             } else {
                 $fixed_amount = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $min_wage = $cd_obj->getUserValue2();
             } else {
                 $min_wage = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $max_wage = $cd_obj->getUserValue3();
             } else {
                 $max_wage = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             $min_wage = bcdiv($min_wage, $annual_pay_periods);
             $max_wage = bcdiv($max_wage, $annual_pay_periods);
             $annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
             Debug::Text('Amount: ' . $fixed_amount . ' Min Wage: ' . $min_wage . ' Max Wage: ' . $max_wage . ' Annual Deduction: ' . $annual_deduction_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($fixed_amount != 0) {
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $annual_deduction_amount);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount >= $min_wage and $amount <= $max_wage) {
                     $retval = $fixed_amount;
                 }
             } else {
                 $retval = 0;
             }
             unset($fixed_amount, $amount, $percent, $min_wage, $max_wage, $annual_deduction_amount);
             break;
         case 52:
             //Fixed Amount (w/Limit)
             if ($this->getUserValue1() == '') {
                 $fixed_amount = $cd_obj->getUserValue1();
             } else {
                 $fixed_amount = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $target_amount = $cd_obj->getUserValue2();
             } else {
                 $target_amount = $this->getUserValue2();
             }
             Debug::Text('Amount: ' . $fixed_amount . ' Target Amount: ' . $target_amount, __FILE__, __LINE__, __METHOD__, 10);
             $retval = 0;
             if ($fixed_amount != 0) {
                 $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount !== $target_amount) {
                     if (abs($fixed_amount) < abs(bcsub($amount, $target_amount))) {
                         //Use full fixed amount
                         Debug::Text('Not within reach of target, use full fixed amount...', __FILE__, __LINE__, __METHOD__, 10);
                         $retval = $fixed_amount;
                     } else {
                         Debug::Text('Within reach of target, use partial fixed amount...', __FILE__, __LINE__, __METHOD__, 10);
                         //Use partial fixed_amount
                         $retval = bcadd(abs($amount), $target_amount);
                     }
                 }
             }
             $retval = abs($retval);
             unset($fixed_amount, $tmp_amount, $amount, $min_limit, $max_limit);
             break;
         case 69:
             // Custom Formulas
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $user_value3 = $cd_obj->getUserValue3();
             } else {
                 $user_value3 = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $user_value4 = $cd_obj->getUserValue4();
             } else {
                 $user_value4 = $this->getUserValue4();
             }
             if ($this->getUserValue5() == '') {
                 $user_value5 = $cd_obj->getUserValue5();
             } else {
                 $user_value5 = $this->getUserValue5();
             }
             if ($this->getUserValue6() == '') {
                 $user_value6 = $cd_obj->getUserValue6();
             } else {
                 $user_value6 = $this->getUserValue6();
             }
             if ($this->getUserValue7() == '') {
                 $user_value7 = $cd_obj->getUserValue7();
             } else {
                 $user_value7 = $this->getUserValue7();
             }
             if ($this->getUserValue8() == '') {
                 $user_value8 = $cd_obj->getUserValue8();
             } else {
                 $user_value8 = $this->getUserValue8();
             }
             if ($this->getUserValue9() == '') {
                 $user_value9 = $cd_obj->getUserValue9();
             } else {
                 $user_value9 = $this->getUserValue9();
             }
             if ($this->getUserValue10() == '') {
                 $user_value10 = $cd_obj->getUserValue10();
             } else {
                 $user_value10 = $this->getUserValue10();
             }
             // evaluate math expressions as the company_value1 and user_value1-10 defined by user.
             $company_value1 = $cd_obj->getCompanyValue1();
             // Custom Formula
             $variables = array();
             $formula_variables = array_keys((array) TTMath::parseColumnsFromFormula($company_value1));
             Debug::Arr($formula_variables, 'Formula Variables: ', __FILE__, __LINE__, __METHOD__, 10);
             if (is_array($formula_variables)) {
                 if (in_array('currency_conversion_rate', $formula_variables) and is_object($this->getUserObject()) and is_object($this->getUserObject()->getCurrencyObject())) {
                     $currency_iso_code = $this->getUserObject()->getCurrencyObject()->getISOCode();
                     $currency_conversion_rate = $this->getUserObject()->getCurrencyObject()->getConversionRate();
                     Debug::Text('Currency Variables: Rate: ' . $currency_conversion_rate . ' ISO: ' . $currency_iso_code, __FILE__, __LINE__, __METHOD__, 10);
                 }
                 //First pass to gather any necessary data based on variables
                 if (in_array('employee_hourly_rate', $formula_variables) or in_array('employee_annual_wage', $formula_variables) or in_array('employee_wage_average_weekly_hours', $formula_variables)) {
                     $uwlf = TTnew('UserWageListFactory');
                     $uwlf->getWageByUserIdAndPayPeriodEndDate($this->getUser(), $pay_period_obj->getEndDate());
                     if ($uwlf->getRecordCount() > 0) {
                         $uwf = $uwlf->getCurrent();
                         $employee_hourly_rate = $uwf->getHourlyRate();
                         $employee_annual_wage = $uwf->getAnnualWage();
                         $employee_wage_average_weekly_hours = TTDate::getHours($uwf->getWeeklyTime());
                     } else {
                         $employee_hourly_rate = 0;
                         $employee_annual_wage = 0;
                         $employee_wage_average_weekly_hours = 0;
                     }
                     Debug::Text('Employee Hourly Rate: ' . $employee_hourly_rate, __FILE__, __LINE__, __METHOD__, 10);
                 }
                 if ($cd_obj->getCompanyValue2() != '' and $cd_obj->getCompanyValue2() > 0 and $cd_obj->getCompanyValue3() != '' and $cd_obj->getCompanyValue3() > 0) {
                     Debug::Text('Formula Lookback enable: ' . $cd_obj->getCompanyValue2(), __FILE__, __LINE__, __METHOD__, 10);
                     foreach ($formula_variables as $formula_variable) {
                         if (strpos($formula_variable, 'lookback_') !== FALSE) {
                             Debug::Text('Lookback variables exist...', __FILE__, __LINE__, __METHOD__, 10);
                             $lookback_dates = $cd_obj->getLookbackStartAndEndDates($pay_period_obj);
                             $lookback_pay_stub_dates = $cd_obj->getLookbackPayStubs($this->getUser(), $pay_period_obj);
                             break;
                         }
                     }
                 }
                 //Second pass to define variables.
                 foreach ($formula_variables as $formula_variable) {
                     if (!isset($variables[$formula_variable])) {
                         switch ($formula_variable) {
                             case 'custom_value1':
                                 $variables[$formula_variable] = $user_value1;
                                 break;
                             case 'custom_value2':
                                 $variables[$formula_variable] = $user_value2;
                                 break;
                             case 'custom_value3':
                                 $variables[$formula_variable] = $user_value3;
                                 break;
                             case 'custom_value4':
                                 $variables[$formula_variable] = $user_value4;
                                 break;
                             case 'custom_value5':
                                 $variables[$formula_variable] = $user_value5;
                                 break;
                             case 'custom_value6':
                                 $variables[$formula_variable] = $user_value6;
                                 break;
                             case 'custom_value7':
                                 $variables[$formula_variable] = $user_value7;
                                 break;
                             case 'custom_value8':
                                 $variables[$formula_variable] = $user_value8;
                                 break;
                             case 'custom_value9':
                                 $variables[$formula_variable] = $user_value9;
                                 break;
                             case 'custom_value10':
                                 $variables[$formula_variable] = $user_value10;
                                 break;
                             case 'employee_hourly_rate':
                                 $variables[$formula_variable] = $employee_hourly_rate;
                                 break;
                             case 'employee_annual_wage':
                                 $variables[$formula_variable] = $employee_annual_wage;
                                 break;
                             case 'employee_wage_average_weekly_hours':
                                 $variables[$formula_variable] = $employee_wage_average_weekly_hours;
                                 break;
                             case 'annual_pay_periods':
                                 $variables[$formula_variable] = $annual_pay_periods;
                                 break;
                             case 'pay_period_start_date':
                                 $variables[$formula_variable] = $pay_period_obj->getStartDate();
                                 break;
                             case 'pay_period_end_date':
                                 $variables[$formula_variable] = $pay_period_obj->getEndDate();
                                 break;
                             case 'pay_period_transaction_date':
                                 $variables[$formula_variable] = $pay_period_obj->getTransactionDate();
                                 break;
                             case 'employee_hire_date':
                                 $variables[$formula_variable] = $this->getUserObject()->getHireDate();
                                 break;
                             case 'employee_termination_date':
                                 $variables[$formula_variable] = $this->getUserObject()->getTerminationDate();
                                 break;
                             case 'employee_birth_date':
                                 $variables[$formula_variable] = $this->getUserObject()->getBirthDate();
                                 break;
                             case 'currency_iso_code':
                                 $variables[$formula_variable] = $currency_iso_code;
                                 break;
                             case 'currency_conversion_rate':
                                 $variables[$formula_variable] = $currency_conversion_rate;
                                 break;
                             case 'include_pay_stub_amount':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 10);
                                 break;
                             case 'include_pay_stub_ytd_amount':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 30);
                                 break;
                             case 'include_pay_stub_units':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 20);
                                 break;
                             case 'include_pay_stub_ytd_units':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 40);
                                 break;
                             case 'exclude_pay_stub_amount':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, NULL, 10);
                                 break;
                             case 'exclude_pay_stub_ytd_amount':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, NULL, 30);
                                 break;
                             case 'exclude_pay_stub_units':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, NULL, 20);
                                 break;
                             case 'exclude_pay_stub_ytd_units':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, NULL, 40);
                                 break;
                             case 'pay_stub_amount':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 10, 10);
                                 break;
                             case 'pay_stub_ytd_amount':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 30, 30);
                                 break;
                             case 'pay_stub_units':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 20, 20);
                                 break;
                             case 'pay_stub_ytd_units':
                                 $variables[$formula_variable] = $cd_obj->getCalculationPayStubAmount($pay_stub_obj, 40, 40);
                                 break;
                                 //Lookback variables.
                             //Lookback variables.
                             case 'lookback_total_pay_stubs':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['total_pay_stubs']) ? $lookback_pay_stub_dates['total_pay_stubs'] : 0;
                                 break;
                             case 'lookback_start_date':
                                 $variables[$formula_variable] = isset($lookback_dates['start_date']) ? $lookback_dates['start_date'] : 0;
                                 break;
                             case 'lookback_end_date':
                                 $variables[$formula_variable] = isset($lookback_dates['end_date']) ? $lookback_dates['end_date'] : 0;
                                 break;
                             case 'lookback_first_pay_stub_start_date':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['first_pay_stub_start_date']) ? $lookback_pay_stub_dates['first_pay_stub_start_date'] : 0;
                                 break;
                             case 'lookback_first_pay_stub_end_date':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['first_pay_stub_end_date']) ? $lookback_pay_stub_dates['first_pay_stub_end_date'] : 0;
                                 break;
                             case 'lookback_first_pay_stub_transaction_date':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['first_pay_stub_transaction_date']) ? $lookback_pay_stub_dates['first_pay_stub_transaction_date'] : 0;
                                 break;
                             case 'lookback_last_pay_stub_start_date':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['last_pay_stub_start_date']) ? $lookback_pay_stub_dates['last_pay_stub_start_date'] : 0;
                                 break;
                             case 'lookback_last_pay_stub_end_date':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['last_pay_stub_end_date']) ? $lookback_pay_stub_dates['last_pay_stub_end_date'] : 0;
                                 break;
                             case 'lookback_last_pay_stub_transaction_date':
                                 $variables[$formula_variable] = isset($lookback_pay_stub_dates['last_pay_stub_transaction_date']) ? $lookback_pay_stub_dates['last_pay_stub_end_date'] : 0;
                                 break;
                             case 'lookback_include_pay_stub_amount':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(10);
                                 break;
                             case 'lookback_include_pay_stub_ytd_amount':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(30);
                                 break;
                             case 'lookback_include_pay_stub_units':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(20);
                                 break;
                             case 'lookback_include_pay_stub_ytd_units':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(40);
                                 break;
                             case 'lookback_exclude_pay_stub_amount':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(NULL, 10);
                                 break;
                             case 'lookback_exclude_pay_stub_ytd_amount':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(NULL, 30);
                                 break;
                             case 'lookback_exclude_pay_stub_units':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(NULL, 20);
                                 break;
                             case 'lookback_exclude_pay_stub_ytd_units':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(NULL, 40);
                                 break;
                             case 'lookback_pay_stub_amount':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(10, 10);
                                 break;
                             case 'lookback_pay_stub_ytd_amount':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(30, 30);
                                 break;
                             case 'lookback_pay_stub_units':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(20, 20);
                                 break;
                             case 'lookback_pay_stub_ytd_units':
                                 $variables[$formula_variable] = $cd_obj->getLookbackCalculationPayStubAmount(40, 40);
                                 break;
                         }
                     }
                 }
                 unset($uwlf, $uwf, $employee_hourly_rate, $employee_annual_wage, $employee_wage_average_weekly_hours, $annual_pay_periods, $lookback_dates, $lookback_pay_stub_dates, $currency_iso_code, $currency_conversion_rate);
             }
             //Debug::Arr( $variables,  'Formula Variable values: ', __FILE__, __LINE__, __METHOD__, 10 );
             Debug::Arr(array(str_replace("\r", '; ', $company_value1), str_replace("\r", '; ', TTMath::translateVariables($company_value1, $variables))), 'Original/Translated Formula: ', __FILE__, __LINE__, __METHOD__, 10);
             $retval = TTMath::evaluate(TTMath::translateVariables($company_value1, $variables));
             Debug::Text('Formula Retval: ' . $retval, __FILE__, __LINE__, __METHOD__, 10);
             break;
         case 80:
             //US Earning Income Credit (EIC). Repealed as of 31-Dec-2010.
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('US', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             if (is_object($this->getUserObject())) {
                 $currency_id = $this->getUserObject()->getCurrency();
                 $pd_obj->setUserCurrency($currency_id);
                 Debug::Text('User Currency ID: ' . $currency_id, __FILE__, __LINE__, __METHOD__, 10);
             }
             $pd_obj->setEICFilingStatus($user_value1);
             $pd_obj->setGrossPayPeriodIncome($amount);
             //Allow negative value, infact it always should be.
             $retval = $pd_obj->getEIC();
             break;
         case 82:
             //US - Medicare - Employee
         //US - Medicare - Employee
         case 83:
             //US - Medicare - Employer
         //US - Medicare - Employer
         case 84:
             //US - Social Security - Employee
         //US - Social Security - Employee
         case 85:
             //US - Social Security - Employer
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('US', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             if (is_object($this->getUserObject())) {
                 $currency_id = $this->getUserObject()->getCurrency();
                 $pd_obj->setUserCurrency($currency_id);
                 Debug::Text('User Currency ID: ' . $currency_id, __FILE__, __LINE__, __METHOD__, 10);
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             switch ($cd_obj->getCalculation()) {
                 case 82:
                     //US - Medicare - Employee
                     $pd_obj->setMedicareFilingStatus($user_value1);
                     $pd_obj->setYearToDateGrossIncome($cd_obj->getCalculationYTDAmount($pay_stub_obj));
                     $retval = $pd_obj->getEmployeeMedicare();
                     break;
                 case 83:
                     //US - Medicare - Employer
                     $retval = $pd_obj->getEmployerMedicare();
                     break;
                 case 84:
                     //US - Social Security - Employee
                     $retval = $pd_obj->getEmployeeSocialSecurity();
                     break;
                 case 85:
                     //US - Social Security - Employer
                     $retval = $pd_obj->getEmployerSocialSecurity();
                     break;
             }
             break;
         case 90:
             //Canada - CPP
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('CA', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setEnableCPPAndEIDeduction(TRUE);
             if ($this->getPayStubEntryAccountLinkObject()->getEmployeeCPP() != '') {
                 Debug::Text('Found Employee CPP account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                 $previous_ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                 $current_ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                 Debug::text('YTD CPP Contribution: Previous Amount: ' . $previous_ytd_cpp_arr['ytd_amount'] . ' Current Amount: ' . $current_ytd_cpp_arr['amount'], __FILE__, __LINE__, __METHOD__, 10);
                 $pd_obj->setYearToDateCPPContribution(bcadd($previous_ytd_cpp_arr['ytd_amount'], $current_ytd_cpp_arr['ytd_amount']));
                 unset($previous_ytd_cpp_arr, $current_ytd_cpp_arr);
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getEmployeeCPP();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 91:
             //Canada - EI
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('CA', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setEnableCPPAndEIDeduction(TRUE);
             if ($this->getPayStubEntryAccountLinkObject()->getEmployeeEI() != '') {
                 Debug::Text('Found Employee EI account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                 $previous_ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                 $current_ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                 Debug::text('YTD EI Contribution: Previous Amount: ' . $previous_ytd_ei_arr['ytd_amount'] . ' Current Amount: ' . $current_ytd_ei_arr['amount'], __FILE__, __LINE__, __METHOD__, 10);
                 $pd_obj->setYearToDateEIContribution(bcadd($previous_ytd_ei_arr['ytd_amount'], $current_ytd_ei_arr['ytd_amount']));
                 unset($previous_ytd_ei_arr, $current_ytd_ei_arr);
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getEmployeeEI();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 100:
             //Federal Income Tax
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue2: ' . $user_value2, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction($this->getCompanyDeductionObject()->getCountry(), NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             if (is_object($this->getUserObject())) {
                 $currency_id = $this->getUserObject()->getCurrency();
                 $pd_obj->setUserCurrency($currency_id);
                 Debug::Text('User Currency ID: ' . $currency_id, __FILE__, __LINE__, __METHOD__, 10);
             }
             if ($this->getCompanyDeductionObject()->getCountry() == 'CA') {
                 //CA
                 $pd_obj->setFederalTotalClaimAmount($user_value1);
                 $pd_obj->setEnableCPPAndEIDeduction(TRUE);
                 //$pself = TTnew( 'PayStubEntryListFactory' );
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeCPP() != '') {
                     Debug::Text('Found Employee CPP account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //Check to see if CPP was calculated on the CURRENT pay stub, if not assume they are CPP exempt.
                     //Single this calculation formula doesn't know directly if the user was CPP exempt or not, we have to assume it by
                     //the calculate CPP on the current pay stub. However if the CPP calculation is done AFTER this, it may mistakenly assume they are exempt.
                     //Make sure we handle the maximum CPP contribution cases properly as well.
                     $current_cpp = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                     if (isset($current_cpp['amount']) and $current_cpp['amount'] == 0) {
                         Debug::Text('Current CPP: ' . $current_cpp['amount'] . ' Setting CPP exempt in Federal Income Tax calculation...', __FILE__, __LINE__, __METHOD__, 10);
                         $pd_obj->setCPPExempt(TRUE);
                     }
                     $ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                     Debug::text('YTD CPP Contribution: ' . $ytd_cpp_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateCPPContribution($ytd_cpp_arr['ytd_amount']);
                     unset($ytd_cpp_arr, $current_cpp);
                 }
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeEI() != '') {
                     Debug::Text('Found Employee EI account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //See comment above regarding CPP exempt.
                     $current_ei = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                     if (isset($current_ei['amount']) and $current_ei['amount'] == 0) {
                         Debug::Text('Current EI: ' . $current_ei['amount'] . ' Setting EI exempt in Federal Income Tax calculation...', __FILE__, __LINE__, __METHOD__, 10);
                         $pd_obj->setEIExempt(TRUE);
                     }
                     $ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                     Debug::text('YTD EI Contribution: ' . $ytd_ei_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateEIContribution($ytd_ei_arr['ytd_amount']);
                     unset($ytd_ei_arr, $current_ei);
                 }
             } elseif ($this->getCompanyDeductionObject()->getCountry() == 'US') {
                 //US
                 $pd_obj->setFederalFilingStatus($user_value1);
                 $pd_obj->setFederalAllowance($user_value2);
             } elseif ($this->getCompanyDeductionObject()->getCountry() == 'CR') {
                 //CR
                 $pd_obj->setFederalFilingStatus($user_value1);
                 //Single/Married
                 $pd_obj->setFederalAllowance($user_value2);
                 //Allownces/Children
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getFederalPayPeriodDeductions();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 200:
             //Province Income Tax
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $user_value3 = $cd_obj->getUserValue3();
             } else {
                 $user_value3 = $this->getUserValue3();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue2: ' . $user_value2, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue3: ' . $user_value3, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction($this->getCompanyDeductionObject()->getCountry(), $this->getCompanyDeductionObject()->getProvince());
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setGrossPayPeriodIncome($amount);
             if ($this->getCompanyDeductionObject()->getCountry() == 'CA') {
                 Debug::Text('Canada Pay Period Deductions...', __FILE__, __LINE__, __METHOD__, 10);
                 $pd_obj->setProvincialTotalClaimAmount($user_value1);
                 $pd_obj->setEnableCPPAndEIDeduction(TRUE);
                 //$pself = TTnew( 'PayStubEntryListFactory' );
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeCPP() != '') {
                     Debug::Text('Found Employee CPP account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //Check to see if CPP was calculated on the CURRENT pay stub, if not assume they are CPP exempt.
                     //Single this calculation formula doesn't know directly if the user was CPP exempt or not, we have to assume it by
                     //the calculate CPP on the current pay stub. However if the CPP calculation is done AFTER this, it may mistakenly assume they are exempt.
                     //Make sure we handle the maximum CPP contribution cases properly as well.
                     $current_cpp = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                     if (isset($current_cpp['amount']) and $current_cpp['amount'] == 0) {
                         Debug::Text('Current CPP: ' . $current_cpp['amount'] . ' Setting CPP exempt in Provincial Income Tax calculation...', __FILE__, __LINE__, __METHOD__, 10);
                         $pd_obj->setCPPExempt(TRUE);
                     }
                     $ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                     Debug::text('YTD CPP Contribution: ' . $ytd_cpp_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateCPPContribution($ytd_cpp_arr['ytd_amount']);
                     unset($ytd_cpp_arr, $current_cpp);
                 }
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeEI() != '') {
                     Debug::Text('Found Employee EI account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //See comment above regarding CPP exempt.
                     $current_ei = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                     if (isset($current_ei['amount']) and $current_ei['amount'] == 0) {
                         Debug::Text('Current EI: ' . $current_ei['amount'] . ' Setting EI exempt in Provincial Income Tax calculation...', __FILE__, __LINE__, __METHOD__, 10);
                         $pd_obj->setEIExempt(TRUE);
                     }
                     $ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                     Debug::text('YTD EI Contribution: ' . $ytd_ei_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateEIContribution($ytd_ei_arr['ytd_amount']);
                     unset($ytd_ei_arr, $current_ei);
                 }
                 $retval = $pd_obj->getProvincialPayPeriodDeductions();
             } elseif ($this->getCompanyDeductionObject()->getCountry() == 'US') {
                 Debug::Text('US Pay Period Deductions...', __FILE__, __LINE__, __METHOD__, 10);
                 //Need to set Federal settings here.
                 $udlf = TTnew('UserDeductionListFactory');
                 $udlf->getByUserIdAndCountryID($user_id, $this->getCompanyDeductionObject()->getCountry());
                 if ($udlf->getRecordCount() > 0) {
                     Debug::Text('Found Federal User Deduction...', __FILE__, __LINE__, __METHOD__, 10);
                     $tmp_ud_obj = $udlf->getCurrent();
                     if ($tmp_ud_obj->getUserValue1() == '') {
                         $tmp_user_value1 = $tmp_ud_obj->getCompanyDeductionObject()->getUserValue1();
                     } else {
                         $tmp_user_value1 = $tmp_ud_obj->getUserValue1();
                     }
                     if ($tmp_ud_obj->getUserValue2() == '') {
                         $tmp_user_value2 = $tmp_ud_obj->getCompanyDeductionObject()->getUserValue2();
                     } else {
                         $tmp_user_value2 = $tmp_ud_obj->getUserValue2();
                     }
                     Debug::Text('TmpUserValue1: ' . $tmp_user_value1, __FILE__, __LINE__, __METHOD__, 10);
                     Debug::Text('TmpUserValue2: ' . $tmp_user_value2, __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setFederalFilingStatus($tmp_user_value1);
                     $pd_obj->setFederalAllowance($tmp_user_value2);
                     unset($tmp_ud_obj, $tmp_user_value1, $tmp_user_value1);
                 }
                 unset($udlf);
                 $pd_obj->setStateFilingStatus($user_value1);
                 $pd_obj->setStateAllowance($user_value2);
                 $pd_obj->setUserValue1($user_value1);
                 $pd_obj->setUserValue2($user_value2);
                 $pd_obj->setUserValue3($user_value3);
                 $retval = $pd_obj->getStatePayPeriodDeductions();
             }
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 300:
             //District Income Tax
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $user_value3 = $cd_obj->getUserValue3();
             } else {
                 $user_value3 = $this->getUserValue3();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue2: ' . $user_value2, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue3: ' . $user_value3, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('District: ' . $this->getCompanyDeductionObject()->getDistrict(), __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction($this->getCompanyDeductionObject()->getCountry(), $this->getCompanyDeductionObject()->getProvince(), $this->getCompanyDeductionObject()->getDistrict());
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setDistrictFilingStatus($user_value1);
             $pd_obj->setDistrictAllowance($user_value2);
             $pd_obj->setUserValue1($user_value1);
             $pd_obj->setUserValue2($user_value2);
             $pd_obj->setUserValue3($user_value3);
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getDistrictPayPeriodDeductions();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
     }
     Debug::Text('Deduction Amount: ' . $retval, __FILE__, __LINE__, __METHOD__, 10);
     //Allow negative values, as some advanced tax bracket setups require this.
     if ($retval < 0) {
         //Debug::Text('Deduction was negative, setting to 0...', __FILE__, __LINE__, __METHOD__,10);
         Debug::Text('Deduction was negative...', __FILE__, __LINE__, __METHOD__, 10);
         //$retval = 0;
     }
     return $retval;
 }
 function testON_2007a_SemiMonthly_Claim1_MedIncome()
 {
     Debug::text('ON - SemiMonthly - Beginning of 2007 01-Jan-07: ', __FILE__, __LINE__, __METHOD__, 10);
     $pd_obj = new PayrollDeduction('CA', 'ON');
     //$pd_obj = new PayrollDeduction();
     //$pd_obj->setCountry('CA');
     //$pd_obj->setProvince('BC');
     $pd_obj->setDate(strtotime('01-Jan-07'));
     $pd_obj->setEnableCPPAndEIDeduction(TRUE);
     //Deduct CPP/EI.
     $pd_obj->setAnnualPayPeriods(24);
     $pd_obj->setFederalTotalClaimAmount(8929);
     $pd_obj->setProvincialTotalClaimAmount(8553);
     $pd_obj->setWCBRate(0.18);
     $pd_obj->setEIExempt(FALSE);
     $pd_obj->setCPPExempt(FALSE);
     $pd_obj->setFederalTaxExempt(FALSE);
     $pd_obj->setProvincialTaxExempt(FALSE);
     $pd_obj->setYearToDateCPPContribution(0);
     $pd_obj->setYearToDateEIContribution(0);
     $pd_obj->setGrossPayPeriodIncome(2830.0);
     $this->assertEquals($this->mf($pd_obj->getGrossPayPeriodIncome()), '2830.00');
     Debug::text('Prov Ded: ' . $pd_obj->getProvincialPayPeriodDeductions(), __FILE__, __LINE__, __METHOD__, 10);
     $this->assertEquals($this->mf($pd_obj->getProvincialPayPeriodDeductions()), '212.50');
     //214.00
 }
 function getDeductionAmount($user_id, $pay_stub_obj, $pay_period_obj)
 {
     if ($user_id == '') {
         Debug::Text('Missing User ID: ', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if (!is_object($pay_stub_obj)) {
         Debug::Text('Missing Pay Stub Object: ', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     if (!is_object($pay_period_obj)) {
         Debug::Text('Missing Pay Period Object: ', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     //Calculates the deduction.
     $cd_obj = $this->getCompanyDeductionObject();
     $annual_pay_periods = $pay_period_obj->getPayPeriodScheduleObject()->getAnnualPayPeriods();
     if (!is_object($cd_obj)) {
         return FALSE;
     }
     require_once Environment::getBasePath() . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'payroll_deduction' . DIRECTORY_SEPARATOR . 'PayrollDeduction.class.php';
     $retval = 0;
     Debug::Text('Company Deduction: ID: ' . $cd_obj->getID() . ' Name: ' . $cd_obj->getName() . ' Calculation ID: ' . $cd_obj->getCalculation(), __FILE__, __LINE__, __METHOD__, 10);
     switch ($cd_obj->getCalculation()) {
         case 10:
             //Basic Percent
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             $retval = bcmul($amount, bcdiv($percent, 100));
             break;
         case 15:
             //Advanced Percent
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $wage_base = $cd_obj->getUserValue2();
             } else {
                 $wage_base = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $exempt_amount = $cd_obj->getUserValue3();
             } else {
                 $exempt_amount = $this->getUserValue3();
             }
             //Annual Wage Base is the maximum earnings that an employee can earn before they are no longer eligible for this deduction
             //Annual Deduction Amount
             Debug::Text('Percent: ' . $percent . ' Wage Base: ' . $wage_base . ' Exempt Amount: ' . $exempt_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 if ($exempt_amount > 0) {
                     $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), bcdiv($exempt_amount, $annual_pay_periods));
                     Debug::Text('Amount After Exemption: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 } else {
                     $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
                     Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 }
                 if ($wage_base > 0) {
                     //*NOTE: If the first pay stub in TimeTrex is near the end of the year, and the employee has already exceeded the wage base amount
                     //the payroll admin needs to make sure they add a YTD Adjustment for each Include PS Accounts that this calculation is based on,
                     //NOT the total amount they have paid for the resulting calculation, as that has no effect whatsoever.
                     //getCalculationYTDAmount is the previous pay stub YTD amount, but it includes any YTD Adjustments in the current pay stub too.
                     $ytd_amount = $cd_obj->getCalculationYTDAmount($pay_stub_obj);
                     Debug::Text('Wage Base is set: ' . $wage_base . ' Amount: ' . $amount . ' Current YTD: ' . $ytd_amount, __FILE__, __LINE__, __METHOD__, 10);
                     //Possible calcations:
                     //
                     //Wage Base: 3000
                     //Amount: 500 YTD: 0		= 500
                     //Amount: 500 YTD: 2900		= 100
                     //Amount: 500 YTD: 3100		= 0
                     //Amount: 3500 YTD: 0		= 3000
                     //AMount: 3500 YTD: 2900	= 100
                     //Amount: 3500 YTD: 3100	= 0
                     //Check to see if YTD is less than wage base.
                     $remaining_wage_base = bcsub($wage_base, $ytd_amount);
                     Debug::Text('Remaining Wage Base to be calculated: ' . $remaining_wage_base, __FILE__, __LINE__, __METHOD__, 10);
                     if ($remaining_wage_base > 0) {
                         if ($amount > $remaining_wage_base) {
                             $amount = $remaining_wage_base;
                         }
                     } else {
                         $amount = 0;
                         //Exceeded wage base, nothing to calculate.
                     }
                     unset($remaining_wage_base);
                 } else {
                     Debug::Text('Wage Base is NOT set: ' . $wage_base, __FILE__, __LINE__, __METHOD__, 10);
                 }
                 $retval = bcmul($amount, bcdiv($percent, 100));
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $ytd_amount, $percent, $wage_base);
             break;
         case 17:
             //Advanced Percent (Range Bracket)
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $min_wage = $cd_obj->getUserValue2();
             } else {
                 $min_wage = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $max_wage = $cd_obj->getUserValue3();
             } else {
                 $max_wage = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             if ($this->getUserValue5() == '') {
                 $annual_fixed_amount = $cd_obj->getUserValue5();
             } else {
                 $annual_fixed_amount = $this->getUserValue5();
             }
             $min_wage = bcdiv($min_wage, $annual_pay_periods);
             $max_wage = bcdiv($max_wage, $annual_pay_periods);
             $annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
             $annual_fixed_amount = bcdiv($annual_fixed_amount, $annual_pay_periods);
             Debug::Text('Percent: ' . $percent . ' Min Wage: ' . $min_wage . ' Max Wage: ' . $max_wage . ' Annual Deduction: ' . $annual_deduction_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $annual_deduction_amount);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount >= $min_wage and $amount <= $max_wage) {
                     $retval = bcadd(bcmul($amount, bcdiv($percent, 100)), $annual_fixed_amount);
                 }
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $percent, $min_wage, $max_wage, $annual_deduction_amount, $annual_fixed_amount);
             break;
         case 18:
             //Advanced Percent (Tax Bracket)
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $wage_base = $cd_obj->getUserValue2();
             } else {
                 $wage_base = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $exempt_amount = $cd_obj->getUserValue3();
             } else {
                 $exempt_amount = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             Debug::Text('Percent: ' . $percent . ' Wage Base: ' . $wage_base . ' Exempt Amount: ' . $exempt_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 if ($exempt_amount > 0) {
                     $pp_exempt_amount = bcdiv($exempt_amount, $annual_pay_periods);
                 } else {
                     $pp_exempt_amount = 0;
                 }
                 //Debug::Text('PP Exempt Amount: '. $pp_exempt_amount, __FILE__, __LINE__, __METHOD__,10);
                 if ($wage_base > 0) {
                     $pp_wage_base_amount = bcdiv($wage_base, $annual_pay_periods);
                 } else {
                     $pp_wage_base_amount = 0;
                 }
                 if ($annual_deduction_amount > 0) {
                     $pp_annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
                 } else {
                     $pp_annual_deduction_amount = 0;
                 }
                 //Debug::Text('PP Wage Base Base Amount: '. $pp_wage_base_amount, __FILE__, __LINE__, __METHOD__,10);
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $pp_annual_deduction_amount);
                 //Debug::Text('Calculation Pay Stub Amount: '. $cd_obj->getCalculationPayStubAmount( $pay_stub_obj ), __FILE__, __LINE__, __METHOD__,10);
                 if ($pp_wage_base_amount > 0 and $amount > $pp_wage_base_amount) {
                     //Debug::Text('Exceeds Wage Base...'. $amount, __FILE__, __LINE__, __METHOD__,10);
                     $amount = bcsub($pp_wage_base_amount, $pp_exempt_amount);
                 } else {
                     //Debug::Text('Under Wage Base...'. $amount, __FILE__, __LINE__, __METHOD__,10);
                     $amount = bcsub($amount, $pp_exempt_amount);
                 }
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 $retval = bcmul($amount, bcdiv($percent, 100));
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $percent, $wage_base, $pp_wage_base_amount, $pp_exempt_amount, $annual_deduction_amount, $pp_annual_deduction_amount);
             break;
         case 19:
             //Advanced Percent (Tax Bracket Alternate)
             /*
             	This is designed to be used for single line item tax calculations, in that the formula looks like this,
             	where only ONE bracket would be applied to the employee, NOT all:
             	Wage between 0 - 10,000 calculate 10%
             	Wage between 10,001 - 20,000 calculate 15% + $1000 (10% of 10,000 as per above)
             	Wage between 20,001 - 30,000 calculate 20% + $2500 (10% of 10,000 as first bracket, and 15% of 10,000 as per 2nd bracket)
             */
             if ($this->getUserValue1() == '') {
                 $percent = $cd_obj->getUserValue1();
             } else {
                 $percent = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $min_wage = $cd_obj->getUserValue2();
             } else {
                 $min_wage = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $max_wage = $cd_obj->getUserValue3();
             } else {
                 $max_wage = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             if ($this->getUserValue5() == '') {
                 $annual_fixed_amount = $cd_obj->getUserValue5();
             } else {
                 $annual_fixed_amount = $this->getUserValue5();
             }
             $min_wage = bcdiv($min_wage, $annual_pay_periods);
             $max_wage = bcdiv($max_wage, $annual_pay_periods);
             $annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
             $annual_fixed_amount = bcdiv($annual_fixed_amount, $annual_pay_periods);
             Debug::Text('Percent: ' . $percent . ' Min Wage: ' . $min_wage . ' Max Wage: ' . $max_wage . ' Annual Deduction: ' . $annual_deduction_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($percent != 0) {
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $annual_deduction_amount);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount >= $min_wage and $amount <= $max_wage) {
                     $retval = bcadd(bcmul(bcsub($amount, $min_wage), bcdiv($percent, 100)), $annual_fixed_amount);
                 }
             } else {
                 $retval = 0;
             }
             if ($percent >= 0 and $retval < 0) {
                 $retval = 0;
             }
             unset($amount, $percent, $min_wage, $max_wage, $annual_deduction_amount, $annual_fixed_amount);
             break;
         case 20:
             //Fixed amount
             if ($this->getUserValue1() == FALSE) {
                 $amount = $cd_obj->getUserValue1();
             } else {
                 $amount = $this->getUserValue1();
             }
             $retval = $amount;
             unset($amount);
             break;
         case 30:
             //Fixed Amount (Range Bracket)
             if ($this->getUserValue1() == '') {
                 $fixed_amount = $cd_obj->getUserValue1();
             } else {
                 $fixed_amount = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $min_wage = $cd_obj->getUserValue2();
             } else {
                 $min_wage = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $max_wage = $cd_obj->getUserValue3();
             } else {
                 $max_wage = $this->getUserValue3();
             }
             if ($this->getUserValue4() == '') {
                 $annual_deduction_amount = $cd_obj->getUserValue4();
             } else {
                 $annual_deduction_amount = $this->getUserValue4();
             }
             $min_wage = bcdiv($min_wage, $annual_pay_periods);
             $max_wage = bcdiv($max_wage, $annual_pay_periods);
             $annual_deduction_amount = bcdiv($annual_deduction_amount, $annual_pay_periods);
             Debug::Text('Amount: ' . $fixed_amount . ' Min Wage: ' . $min_wage . ' Max Wage: ' . $max_wage . ' Annual Deduction: ' . $annual_deduction_amount, __FILE__, __LINE__, __METHOD__, 10);
             if ($fixed_amount != 0) {
                 $amount = bcsub($cd_obj->getCalculationPayStubAmount($pay_stub_obj), $annual_deduction_amount);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount >= $min_wage and $amount <= $max_wage) {
                     $retval = $fixed_amount;
                 }
             } else {
                 $retval = 0;
             }
             unset($fixed_amount, $amount, $percent, $min_wage, $max_wage, $annual_deduction_amount);
             break;
         case 52:
             //Fixed Amount (w/Limit)
             if ($this->getUserValue1() == '') {
                 $fixed_amount = $cd_obj->getUserValue1();
             } else {
                 $fixed_amount = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $target_amount = $cd_obj->getUserValue2();
             } else {
                 $target_amount = $this->getUserValue2();
             }
             Debug::Text('Amount: ' . $fixed_amount . ' Target Amount: ' . $target_amount, __FILE__, __LINE__, __METHOD__, 10);
             $retval = 0;
             if ($fixed_amount != 0) {
                 $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
                 Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
                 if ($amount !== $target_amount) {
                     if (abs($fixed_amount) < abs(bcsub($amount, $target_amount))) {
                         //Use full fixed amount
                         Debug::Text('Not within reach of target, use full fixed amount...', __FILE__, __LINE__, __METHOD__, 10);
                         $retval = $fixed_amount;
                     } else {
                         Debug::Text('Within reach of target, use partial fixed amount...', __FILE__, __LINE__, __METHOD__, 10);
                         //Use partial fixed_amount
                         $retval = bcadd(abs($amount), $target_amount);
                     }
                 }
             }
             $retval = abs($retval);
             unset($fixed_amount, $tmp_amount, $amount, $min_limit, $max_limit);
             break;
         case 80:
             //US Earning Income Credit (EIC)
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('US', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             if (is_object($this->getUserObject())) {
                 $currency_id = $this->getUserObject()->getCurrency();
                 $pd_obj->setUserCurrency($currency_id);
                 Debug::Text('User Currency ID: ' . $currency_id, __FILE__, __LINE__, __METHOD__, 10);
             }
             $pd_obj->setEICFilingStatus($user_value1);
             $pd_obj->setGrossPayPeriodIncome($amount);
             //Allow negative value, infact it always should be.
             $retval = $pd_obj->getEIC();
             break;
         case 90:
             //Canada - CPP
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('CA', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setEnableCPPAndEIDeduction(TRUE);
             if ($this->getPayStubEntryAccountLinkObject()->getEmployeeCPP() != '') {
                 Debug::Text('Found Employee CPP account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                 $previous_ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                 $current_ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                 Debug::text('YTD CPP Contribution: Previous Amount: ' . $previous_ytd_cpp_arr['ytd_amount'] . ' Current Amount: ' . $current_ytd_cpp_arr['amount'], __FILE__, __LINE__, __METHOD__, 10);
                 $pd_obj->setYearToDateCPPContribution(bcadd($previous_ytd_cpp_arr['ytd_amount'], $current_ytd_cpp_arr['ytd_amount']));
                 unset($previous_ytd_cpp_arr, $current_ytd_cpp_arr);
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getEmployeeCPP();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 91:
             //Canada - EI
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction('CA', NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setEnableCPPAndEIDeduction(TRUE);
             if ($this->getPayStubEntryAccountLinkObject()->getEmployeeEI() != '') {
                 Debug::Text('Found Employee EI account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                 $previous_ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                 $current_ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('current', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                 Debug::text('YTD EI Contribution: Previous Amount: ' . $previous_ytd_ei_arr['ytd_amount'] . ' Current Amount: ' . $current_ytd_ei_arr['amount'], __FILE__, __LINE__, __METHOD__, 10);
                 $pd_obj->setYearToDateEIContribution(bcadd($previous_ytd_ei_arr['ytd_amount'], $current_ytd_ei_arr['ytd_amount']));
                 unset($previous_ytd_ei_arr, $current_ytd_ei_arr);
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getEmployeeEI();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 100:
             //Federal Income Tax
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue2: ' . $user_value2, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction($this->getCompanyDeductionObject()->getCountry(), NULL);
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             if (is_object($this->getUserObject())) {
                 $currency_id = $this->getUserObject()->getCurrency();
                 $pd_obj->setUserCurrency($currency_id);
                 Debug::Text('User Currency ID: ' . $currency_id, __FILE__, __LINE__, __METHOD__, 10);
             }
             if ($this->getCompanyDeductionObject()->getCountry() == 'CA') {
                 //CA
                 $pd_obj->setFederalTotalClaimAmount($user_value1);
                 $pd_obj->setEnableCPPAndEIDeduction(TRUE);
                 //$pself = new PayStubEntryListFactory();
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeCPP() != '') {
                     Debug::Text('Found Employee CPP account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //$ytd_cpp_arr = $pself->getYTDAmountSumByUserIdAndEntryNameIDAndYear( $this->getUser(), $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP(), $pay_period_obj->getTransactionDate() );
                     $ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                     Debug::text('YTD CPP Contribution: ' . $ytd_cpp_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateCPPContribution($ytd_cpp_arr['ytd_amount']);
                     unset($ytd_cpp_arr);
                 }
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeEI() != '') {
                     Debug::Text('Found Employee EI account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //$ytd_ei_arr = $pself->getYTDAmountSumByUserIdAndEntryNameIDAndYear( $this->getUser(), $this->getPayStubEntryAccountLinkObject()->getEmployeeEI(), $pay_period_obj->getTransactionDate() );
                     $ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                     Debug::text('YTD EI Contribution: ' . $ytd_ei_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateEIContribution($ytd_ei_arr['ytd_amount']);
                     unset($ytd_ei_arr);
                 }
             } elseif ($this->getCompanyDeductionObject()->getCountry() == 'US') {
                 //US
                 $pd_obj->setFederalFilingStatus($user_value1);
                 $pd_obj->setFederalAllowance($user_value2);
             } elseif ($this->getCompanyDeductionObject()->getCountry() == 'CR') {
                 //CR
                 $pd_obj->setFederalFilingStatus($user_value1);
                 //Single/Married
                 $pd_obj->setFederalAllowance($user_value2);
                 //Allownces/Children
             }
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getFederalPayPeriodDeductions();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 200:
             //Province Income Tax
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $user_value3 = $cd_obj->getUserValue3();
             } else {
                 $user_value3 = $this->getUserValue3();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue2: ' . $user_value2, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue3: ' . $user_value3, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction($this->getCompanyDeductionObject()->getCountry(), $this->getCompanyDeductionObject()->getProvince());
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setGrossPayPeriodIncome($amount);
             if ($this->getCompanyDeductionObject()->getCountry() == 'CA') {
                 Debug::Text('Canada Pay Period Deductions...', __FILE__, __LINE__, __METHOD__, 10);
                 $pd_obj->setProvincialTotalClaimAmount($user_value1);
                 $pd_obj->setEnableCPPAndEIDeduction(TRUE);
                 //$pself = new PayStubEntryListFactory();
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeCPP() != '') {
                     Debug::Text('Found Employee CPP account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     $ytd_cpp_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeCPP());
                     Debug::text('YTD CPP Contribution: ' . $ytd_cpp_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateCPPContribution($ytd_cpp_arr['ytd_amount']);
                     unset($ytd_cpp_arr);
                 }
                 if ($this->getPayStubEntryAccountLinkObject()->getEmployeeEI() != '') {
                     Debug::Text('Found Employee EI account link!: ', __FILE__, __LINE__, __METHOD__, 10);
                     //$ytd_ei_arr = $pself->getYTDAmountSumByUserIdAndEntryNameIDAndYear( $this->getUser(), $this->getPayStubEntryAccountLinkObject()->getEmployeeEI(), $pay_period_obj->getTransactionDate() );
                     $ytd_ei_arr = $pay_stub_obj->getSumByEntriesArrayAndTypeIDAndPayStubAccountID('previous', NULL, $this->getPayStubEntryAccountLinkObject()->getEmployeeEI());
                     Debug::text('YTD EI Contribution: ' . $ytd_ei_arr['ytd_amount'], __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setYearToDateEIContribution($ytd_ei_arr['ytd_amount']);
                     unset($ytd_ei_arr);
                 }
                 $retval = $pd_obj->getProvincialPayPeriodDeductions();
             } elseif ($this->getCompanyDeductionObject()->getCountry() == 'US') {
                 Debug::Text('US Pay Period Deductions...', __FILE__, __LINE__, __METHOD__, 10);
                 //Need to set Federal settings here.
                 $udlf = new UserDeductionListFactory();
                 $udlf->getByUserIdAndCountryID($user_id, $this->getCompanyDeductionObject()->getCountry());
                 if ($udlf->getRecordCount() > 0) {
                     Debug::Text('Found Federal User Deduction...', __FILE__, __LINE__, __METHOD__, 10);
                     $tmp_ud_obj = $udlf->getCurrent();
                     if ($tmp_ud_obj->getUserValue1() == '') {
                         $tmp_user_value1 = $tmp_ud_obj->getCompanyDeductionObject()->getUserValue1();
                     } else {
                         $tmp_user_value1 = $tmp_ud_obj->getUserValue1();
                     }
                     if ($tmp_ud_obj->getUserValue2() == '') {
                         $tmp_user_value2 = $tmp_ud_obj->getCompanyDeductionObject()->getUserValue2();
                     } else {
                         $tmp_user_value2 = $tmp_ud_obj->getUserValue2();
                     }
                     Debug::Text('TmpUserValue1: ' . $tmp_user_value1, __FILE__, __LINE__, __METHOD__, 10);
                     Debug::Text('TmpUserValue2: ' . $tmp_user_value2, __FILE__, __LINE__, __METHOD__, 10);
                     $pd_obj->setFederalFilingStatus($tmp_user_value1);
                     $pd_obj->setFederalAllowance($tmp_user_value2);
                     unset($tmp_ud_obj, $tmp_user_value1, $tmp_user_value1);
                 }
                 unset($udlf);
                 $pd_obj->setStateFilingStatus($user_value1);
                 $pd_obj->setStateAllowance($user_value2);
                 $pd_obj->setUserValue1($user_value1);
                 $pd_obj->setUserValue2($user_value2);
                 $pd_obj->setUserValue3($user_value3);
                 $retval = $pd_obj->getStatePayPeriodDeductions();
             }
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
         case 300:
             //District Income Tax
             if ($this->getUserValue1() == '') {
                 $user_value1 = $cd_obj->getUserValue1();
             } else {
                 $user_value1 = $this->getUserValue1();
             }
             if ($this->getUserValue2() == '') {
                 $user_value2 = $cd_obj->getUserValue2();
             } else {
                 $user_value2 = $this->getUserValue2();
             }
             if ($this->getUserValue3() == '') {
                 $user_value3 = $cd_obj->getUserValue3();
             } else {
                 $user_value3 = $this->getUserValue3();
             }
             Debug::Text('UserValue1: ' . $user_value1, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue2: ' . $user_value2, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('UserValue3: ' . $user_value3, __FILE__, __LINE__, __METHOD__, 10);
             $amount = $cd_obj->getCalculationPayStubAmount($pay_stub_obj);
             Debug::Text('Amount: ' . $amount, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('Annual Pay Periods: ' . $annual_pay_periods, __FILE__, __LINE__, __METHOD__, 10);
             Debug::Text('District: ' . $this->getCompanyDeductionObject()->getDistrict(), __FILE__, __LINE__, __METHOD__, 10);
             $pd_obj = new PayrollDeduction($this->getCompanyDeductionObject()->getCountry(), $this->getCompanyDeductionObject()->getProvince(), $this->getCompanyDeductionObject()->getDistrict());
             $pd_obj->setCompany($this->getUserObject()->getCompany());
             $pd_obj->setUser($this->getUser());
             $pd_obj->setDate($pay_period_obj->getTransactionDate());
             $pd_obj->setAnnualPayPeriods($annual_pay_periods);
             $pd_obj->setDistrictFilingStatus($user_value1);
             $pd_obj->setDistrictAllowance($user_value2);
             $pd_obj->setUserValue1($user_value1);
             $pd_obj->setUserValue2($user_value2);
             $pd_obj->setUserValue3($user_value3);
             $pd_obj->setGrossPayPeriodIncome($amount);
             $retval = $pd_obj->getDistrictPayPeriodDeductions();
             if ($retval < 0) {
                 $retval = 0;
             }
             break;
     }
     Debug::Text('Deduction Amount: ' . $retval, __FILE__, __LINE__, __METHOD__, 10);
     //Allow negative values, as some advanced tax bracket setups require this.
     if ($retval < 0) {
         //Debug::Text('Deduction was negative, setting to 0...', __FILE__, __LINE__, __METHOD__,10);
         Debug::Text('Deduction was negative...', __FILE__, __LINE__, __METHOD__, 10);
         //$retval = 0;
     }
     return $retval;
 }
 function testPE_2008a_SemiMonthly_Claim1_MedIncome()
 {
     Debug::text('PE - SemiMonthly - Beginning of 2008 01-Jan-08: ', __FILE__, __LINE__, __METHOD__, 10);
     $pd_obj = new PayrollDeduction('CA', 'PE');
     $pd_obj->setDate(strtotime('01-Jan-08'));
     $pd_obj->setEnableCPPAndEIDeduction(TRUE);
     //Deduct CPP/EI.
     $pd_obj->setAnnualPayPeriods(24);
     $pd_obj->setFederalTotalClaimAmount(9600);
     $pd_obj->setProvincialTotalClaimAmount(7708);
     $pd_obj->setWCBRate(0.18);
     $pd_obj->setEIExempt(FALSE);
     $pd_obj->setCPPExempt(FALSE);
     $pd_obj->setFederalTaxExempt(FALSE);
     $pd_obj->setProvincialTaxExempt(FALSE);
     $pd_obj->setYearToDateCPPContribution(0);
     $pd_obj->setYearToDateEIContribution(0);
     $pd_obj->setGrossPayPeriodIncome(2763.0);
     $this->assertEquals($this->mf($pd_obj->getGrossPayPeriodIncome()), '2763.00');
     Debug::text('Prov Ded: ' . $pd_obj->getProvincialPayPeriodDeductions(), __FILE__, __LINE__, __METHOD__, 10);
     $this->assertEquals($this->mf($pd_obj->getProvincialPayPeriodDeductions()), '288.09');
     //285.90
 }