diff --git a/CRM/Contribute/BAO/Contribution/Utils.php b/CRM/Contribute/BAO/Contribution/Utils.php index 6ea7c5b271fd..a18f30e4a6cb 100644 --- a/CRM/Contribute/BAO/Contribution/Utils.php +++ b/CRM/Contribute/BAO/Contribution/Utils.php @@ -473,10 +473,12 @@ public static function getFirstLastDetails($contactID) { * array of tax amount * */ - public static function calculateTaxAmount($amount, $taxRate) { + public static function calculateTaxAmount($amount, $taxRate, $htmlType = NULL) { $taxAmount = array(); - $taxAmount['tax_amount'] = round(($taxRate / 100) * CRM_Utils_Rule::cleanMoney($amount), 2); - + $taxAmount['tax_amount'] = ($taxRate / 100) * CRM_Utils_Rule::cleanMoney($amount); + if ($htmlType != 'Text') { + $taxAmount['tax_amount'] = round($taxAmount['tax_amount'], 2); + } return $taxAmount; } diff --git a/CRM/Contribute/Form/Contribution.php b/CRM/Contribute/Form/Contribution.php index 450c1bac94fa..4deb0ff73d56 100644 --- a/CRM/Contribute/Form/Contribution.php +++ b/CRM/Contribute/Form/Contribution.php @@ -1416,6 +1416,10 @@ public function testSubmit($params, $action, $creditCardMode = NULL) { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->controller = new CRM_Core_Controller(); + if (CRM_Utils_Array::value('price_set_id', $params)) { + $this->_priceSet = current(CRM_Price_BAO_PriceSet::getSetDetail($params['price_set_id'])); + } + CRM_Contribute_Form_AdditionalInfo::buildPremium($this); $this->_fields = array(); diff --git a/CRM/Contribute/Form/Contribution/Confirm.php b/CRM/Contribute/Form/Contribution/Confirm.php index 3c385d14d9f9..a654645d3b19 100644 --- a/CRM/Contribute/Form/Contribution/Confirm.php +++ b/CRM/Contribute/Form/Contribution/Confirm.php @@ -1914,7 +1914,7 @@ public static function submit($params) { $form->controller = new CRM_Contribute_Controller_Contribution(); $params['invoiceID'] = md5(uniqid(rand(), TRUE)); $paramsProcessedForForm = $form->_params = self::getFormParams($params['id'], $params); - $form->_amount = $params['amount']; + $form->_amount = CRM_Utils_Array::value('amount', $params, 0); // hack these in for test support. $form->_fields['billing_first_name'] = 1; $form->_fields['billing_last_name'] = 1; @@ -1951,7 +1951,7 @@ public static function submit($params) { } $priceFields = $priceFields[$priceSetID]['fields']; - CRM_Price_BAO_PriceSet::processAmount($priceFields, $paramsProcessedForForm, $lineItems, 'civicrm_contribution'); + CRM_Price_BAO_PriceSet::processAmount($priceFields, $form->_params, $lineItems, 'civicrm_contribution'); $form->_lineItem = array($priceSetID => $lineItems); $membershipPriceFieldIDs = array(); foreach ((array) $lineItems as $lineItem) { diff --git a/CRM/Price/BAO/PriceField.php b/CRM/Price/BAO/PriceField.php index 5b56b2eeaabb..3b8bbbb48221 100644 --- a/CRM/Price/BAO/PriceField.php +++ b/CRM/Price/BAO/PriceField.php @@ -596,7 +596,7 @@ public static function addQuickFormElement( * @return array * array of options */ - public static function getOptions($fieldId, $inactiveNeeded = FALSE, $reset = FALSE, $isDefaultContributionPriceSet = FALSE) { + public static function getOptions($fieldId, $inactiveNeeded = FALSE, $reset = FALSE, $isDefaultContributionPriceSet = FALSE, $htmlType = NULL) { static $options = array(); if ($reset) { $options = array(); @@ -617,7 +617,7 @@ public static function getOptions($fieldId, $inactiveNeeded = FALSE, $reset = FA foreach ($options[$fieldId] as $priceFieldId => $priceFieldValues) { if (isset($priceFieldValues['financial_type_id']) && array_key_exists($priceFieldValues['financial_type_id'], $taxRates) && !$isDefaultContributionPriceSet) { $options[$fieldId][$priceFieldId]['tax_rate'] = $taxRates[$priceFieldValues['financial_type_id']]; - $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($priceFieldValues['amount'], $options[$fieldId][$priceFieldId]['tax_rate']); + $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($priceFieldValues['amount'], $options[$fieldId][$priceFieldId]['tax_rate'], $htmlType); $options[$fieldId][$priceFieldId]['tax_amount'] = $taxAmount['tax_amount']; } } diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php index 39fa2d567cf8..b199b6e24c9b 100644 --- a/CRM/Price/BAO/PriceSet.php +++ b/CRM/Price/BAO/PriceSet.php @@ -592,7 +592,7 @@ public static function getSetDetail($setID, $required = TRUE, $validOnly = FALSE } $setTree[$setID]['fields'][$fieldID][$field] = $dao->$field; } - $setTree[$setID]['fields'][$fieldID]['options'] = CRM_Price_BAO_PriceField::getOptions($fieldID, FALSE, FALSE, $isDefaultContributionPriceSet); + $setTree[$setID]['fields'][$fieldID]['options'] = CRM_Price_BAO_PriceField::getOptions($fieldID, FALSE, FALSE, $isDefaultContributionPriceSet, $dao->html_type); } // also get the pre and post help from this price set @@ -1672,6 +1672,7 @@ public static function setLineItem($field, $lineItem, $optionValueId, &$totalTax else { $taxAmount = $field['options'][$optionValueId]['tax_amount']; } + $taxAmount = round($taxAmount, 2); $taxRate = $field['options'][$optionValueId]['tax_rate']; $lineItem[$optionValueId]['tax_amount'] = $taxAmount; $lineItem[$optionValueId]['tax_rate'] = $taxRate; diff --git a/api/v3/examples/ContributionPage/Submit.php b/api/v3/examples/ContributionPage/Submit.php index c26b197384bd..d318e1091b37 100644 --- a/api/v3/examples/ContributionPage/Submit.php +++ b/api/v3/examples/ContributionPage/Submit.php @@ -9,16 +9,12 @@ */ function contribution_page_submit_example() { $params = array( - 'price_3' => '', 'id' => 1, - 'amount' => 10, + 'amount' => 100, 'billing_first_name' => 'Billy', 'billing_middle_name' => 'Goat', 'billing_last_name' => 'Gruff', 'email' => 'billy@goat.gruff', - 'selectMembership' => array( - '0' => 1, - ), 'payment_processor_id' => 1, 'credit_card_number' => '4111111111111111', 'credit_card_type' => 'Visa', @@ -27,9 +23,11 @@ function contribution_page_submit_example() { 'Y' => 2040, ), 'cvv2' => 123, - 'is_recur' => 1, - 'frequency_interval' => 1, - 'frequency_unit' => 'month', + 'pledge_frequency_interval' => 1, + 'pledge_frequency_unit' => 'week', + 'pledge_installments' => 3, + 'is_pledge' => TRUE, + 'pledge_block_id' => 2, ); try{ @@ -41,7 +39,8 @@ function contribution_page_submit_example() { $errorCode = $e->getErrorCode(); $errorData = $e->getExtraParams(); return array( - 'error' => $errorMessage, + 'is_error' => 1, + 'error_message' => $errorMessage, 'error_code' => $errorCode, 'error_data' => $errorData, ); @@ -70,7 +69,7 @@ function contribution_page_submit_expectedresult() { /* * This example has been generated from the API test suite. -* The test that created it is called "testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed" +* The test that created it is called "testSubmitPledgePaymentPaymentProcessorRecurFuturePayment" * and can be found at: * https://github.com/civicrm/civicrm-core/blob/master/tests/phpunit/api/v3/ContributionPageTest.php * diff --git a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php index 5d0bffdf934c..b29b4d97478e 100644 --- a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php +++ b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php @@ -851,4 +851,82 @@ public function testSubmitWithOutSaleTax() { $this->assertTrue(empty($lineItem['tax_amount'])); } + /** + * Test form submission CRM-16228. + */ + public function testSubmitContributionPageWithPriceSetHavingTaxCRM16228() { + $this->enableTaxAndInvoicing(); + $financialType = $this->createFinancialType(); + $this->relationForFinancialTypeWithFinancialAccount($financialType['id'], 5); + $priceSetID = $this->createContributionPriceSet($financialType['id']); + $priceFieldId = $this->addTaxTextPriceFields($priceSetID, $financialType['id'], '16.85'); + $form = new CRM_Contribute_Form_Contribution(); + $submitParams = array( + 'financial_type_id' => $financialType['id'], + 'receive_date' => '04/21/2015', + 'receive_date_time' => '11:27PM', + 'contact_id' => $this->_individualId, + 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), + 'contribution_status_id' => 1, + 'price_set_id' => $priceSetID, + 'price_' . $priceFieldId => 10, + ); + $form->testSubmit($submitParams, CRM_Core_Action::ADD); + $contribution = $this->callAPISuccessGetSingle('Contribution', + array( + 'contact_id' => $this->_individualId, + 'return' => array('tax_amount', 'total_amount'), + ) + ); + $this->assertEquals($contribution['tax_amount'], '8.43', 'Wrong Tax amount is calculated and stored.'); + $this->assertEquals($contribution['total_amount'], '176.93', 'Total amount no matching.'); + $lineItem = $this->callAPISuccessGetSingle('LineItem', array( + 'contribution_id' => $contribution['id'], + )); + $this->assertEquals($lineItem['tax_amount'], '8.43', 'Wrong Tax amount is calculated and stored.'); + $this->assertEquals($lineItem['line_total'], '168.50', 'Total amount no matching.'); + } + + /** + * Test form submission CRM-16228. + */ + public function testSubmitContributionPageWithPriceSetHaving2PriceFieldTaxCRM16228() { + $this->enableTaxAndInvoicing(); + $financialType = $this->createFinancialType(); + $this->relationForFinancialTypeWithFinancialAccount($financialType['id'], 5); + $priceSetID = $this->createContributionPriceSet($financialType['id']); + $priceFieldId = $this->addTaxTextPriceFields($priceSetID, $financialType['id'], '16.85'); + $priceFieldId2 = $this->addTaxTextPriceFields($priceSetID, $financialType['id'], '13.33'); + $form = new CRM_Contribute_Form_Contribution(); + $submitParams = array( + 'financial_type_id' => $financialType['id'], + 'receive_date' => '04/21/2015', + 'receive_date_time' => '11:27PM', + 'contact_id' => $this->_individualId, + 'payment_instrument_id' => array_search('Check', $this->paymentInstruments), + 'contribution_status_id' => 1, + 'price_set_id' => $priceSetID, + 'price_' . $priceFieldId => 10, + 'price_' . $priceFieldId2 => 100, + ); + $form->testSubmit($submitParams, CRM_Core_Action::ADD); + $contribution = $this->callAPISuccessGetSingle('Contribution', + array( + 'contact_id' => $this->_individualId, + 'return' => array('tax_amount', 'total_amount'), + ) + ); + $this->assertEquals($contribution['tax_amount'], '75.08', 'Wrong Tax amount is calculated and stored.'); + $this->assertEquals($contribution['total_amount'], '1576.58', 'Total amount no matching.'); + $lineItem = $this->callAPISuccess('LineItem', 'get', array( + 'contribution_id' => $contribution['id'], + )); + $lineTotal = array('1333', '168.50'); + $lineTaxAmount = array('66.65', '8.43'); + foreach ($lineItem['values'] as $line) { + $this->assertEquals(CRM_Utils_Array::value('tax_amount', $line), array_pop($lineTaxAmount), 'Wrong Tax amount is calculated and stored.'); + $this->assertEquals($line['line_total'], array_pop($lineTotal), 'Total amount no matching.'); + } + } + } diff --git a/tests/phpunit/CiviTest/CiviUnitTestCase.php b/tests/phpunit/CiviTest/CiviUnitTestCase.php index c4aba681eea5..e470b20db1f9 100644 --- a/tests/phpunit/CiviTest/CiviUnitTestCase.php +++ b/tests/phpunit/CiviTest/CiviUnitTestCase.php @@ -3674,13 +3674,13 @@ protected function enableTaxAndInvoicing($params = array()) { * * @return obj */ - protected function relationForFinancialTypeWithFinancialAccount($financialTypeId) { + protected function relationForFinancialTypeWithFinancialAccount($financialTypeId, $taxRate = 10) { $params = array( 'name' => 'Sales tax account ' . substr(sha1(rand()), 0, 4), 'financial_account_type_id' => key(CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name LIKE 'Liability' ")), 'is_deductible' => 1, 'is_tax' => 1, - 'tax_rate' => 10, + 'tax_rate' => $taxRate, 'is_active' => 1, ); $account = CRM_Financial_BAO_FinancialAccount::add($params); @@ -3767,4 +3767,43 @@ public function createPriceSetWithPage($entity = NULL, $params = array()) { $this->_ids['membership_type'] = $membershipTypeID; } + /** + * Function to add additional price fields to priceset with tax. + * @param int $priceSetID + * @param int $financialTypeId + * @param float $textFieldAmount + */ + public function addTaxTextPriceFields($priceSetID, $financialTypeId, $textFieldAmount) { + $priceField = $this->callAPISuccess('price_field', 'create', array( + 'price_set_id' => $priceSetID, + 'label' => 'No. of Person(s)' . substr(sha1(rand()), 0, 7), + 'html_type' => 'Text', + )); + $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array( + 'price_set_id' => $priceSetID, + 'price_field_id' => $priceField['id'], + 'label' => 'No. of Person(s)' . substr(sha1(rand()), 0, 7), + 'financial_type_id' => $financialTypeId, + 'amount' => $textFieldAmount, + )); + // clear cached values in this function. + CRM_Price_BAO_PriceField::getOptions(NULL, FALSE, TRUE); + return $priceField['id']; + } + + /** + * Add Contribution PriceSet. + * @param string $financialType + */ + public function createContributionPriceSet($financialType = 'Donation') { + $params = array( + 'is_quick_config' => 0, + 'extends' => 'CiviContribute', + 'financial_type_id' => $financialType, + 'title' => 'Price-set-test' . substr(sha1(rand()), 0, 7), + ); + $priceSet = $this->callAPISuccess('price_set', 'create', $params); + return $priceSet['id']; + } + } diff --git a/tests/phpunit/api/v3/ContributionPageTest.php b/tests/phpunit/api/v3/ContributionPageTest.php index d652063920d3..35662962454a 100644 --- a/tests/phpunit/api/v3/ContributionPageTest.php +++ b/tests/phpunit/api/v3/ContributionPageTest.php @@ -1416,4 +1416,86 @@ public function addPriceFields(&$params) { ); } + /** + * Test form submission CRM-16228. + */ + public function testSubmitContributionPageWithPriceSetHavingTaxCRM16228() { + $this->_priceSetParams['is_quick_config'] = 0; + $this->enableTaxAndInvoicing(); + $financialType = $this->createFinancialType(); + $financialAccount = $this->relationForFinancialTypeWithFinancialAccount($financialType['id'], 5); + $this->setUpContributionPage(); + $submitParams = array( + 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']), + 'id' => (int) $this->_ids['contribution_page'], + 'first_name' => 'Billy', + 'last_name' => 'Gruff', + 'email' => 'billy@goat.gruff', + 'is_pay_later' => TRUE, + ); + $priceSetID = reset($this->_ids['price_set']); + $priceFieldId = $this->addTaxTextPriceFields($priceSetID, $financialType['id'], '16.85'); + $submitParams['price_' . $priceFieldId] = 100; + $this->callAPISuccess('contribution_page', 'submit', $submitParams); + $contribution = $this->callAPISuccessGetSingle('contribution', array( + 'contribution_page_id' => $this->_ids['contribution_page'], + 'contribution_status_id' => 2, + 'return' => array('total_amount', 'tax_amount'), + )); + $this->assertEquals($contribution['tax_amount'], '84.25', 'Wrong Tax amount is calculated and stored.'); + // 10 + (100 * 16.85) + (100 * 16.85 * 0.05) + $this->assertEquals($contribution['total_amount'], '1779.25', 'Total amount no matching.'); + $lineItem = $this->callAPISuccess('LineItem', 'get', array( + 'contribution_id' => $contribution['id'], + )); + $lineTotal = array(1685, 10); + $lineTaxAmount = array('84.25', NULL); + foreach ($lineItem['values'] as $line) { + $this->assertEquals(CRM_Utils_Array::value('tax_amount', $line), array_pop($lineTaxAmount), 'Wrong Tax amount is calculated and stored.'); + $this->assertEquals($line['line_total'], array_pop($lineTotal), 'Total amount no matching.'); + } + } + + /** + * Test form submission CRM-16228. + */ + public function testSubmitContributionPageWithPriceSetHaving2PriceFieldTaxCRM16228() { + $this->_priceSetParams['is_quick_config'] = 0; + $this->enableTaxAndInvoicing(); + $financialType = $this->createFinancialType(); + $financialAccount = $this->relationForFinancialTypeWithFinancialAccount($financialType['id'], 5); + $this->setUpContributionPage(); + $submitParams = array( + 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']), + 'id' => (int) $this->_ids['contribution_page'], + 'first_name' => 'Billy', + 'last_name' => 'Gruff', + 'email' => 'billy@goat.gruff', + 'is_pay_later' => TRUE, + ); + $priceSetID = reset($this->_ids['price_set']); + $priceFieldId = $this->addTaxTextPriceFields($priceSetID, $financialType['id'], '16.85'); + $submitParams['price_' . $priceFieldId] = 100; + $priceFieldId = $this->addTaxTextPriceFields($priceSetID, $financialType['id'], '13.33'); + $submitParams['price_' . $priceFieldId] = 10; + $this->callAPISuccess('contribution_page', 'submit', $submitParams); + $contribution = $this->callAPISuccessGetSingle('contribution', array( + 'contribution_page_id' => $this->_ids['contribution_page'], + 'contribution_status_id' => 2, + 'return' => array('total_amount', 'tax_amount'), + )); + $this->assertEquals($contribution['tax_amount'], '90.92', 'Wrong Tax amount is calculated and stored.'); + // 10 + (100 * 16.85) + (100 * 16.85 * 0.05) + (10 * 13.33) + (10 * 13.33 * 0.05) + $this->assertEquals($contribution['total_amount'], '1919.22', 'Total amount no matching.'); + $lineItem = $this->callAPISuccess('LineItem', 'get', array( + 'contribution_id' => $contribution['id'], + )); + $lineTotal = array('133.30', '1685', '10'); + $lineTaxAmount = array('6.67', '84.25', NULL); + foreach ($lineItem['values'] as $line) { + $this->assertEquals(CRM_Utils_Array::value('tax_amount', $line), array_pop($lineTaxAmount), 'Wrong Tax amount is calculated and stored.'); + $this->assertEquals($line['line_total'], array_pop($lineTotal), 'Total amount no matching.'); + } + } + }