From 265807d1836f51e5eb5c20d30021f8c5cc86a7cf Mon Sep 17 00:00:00 2001 From: Pradeep Nayak Date: Tue, 1 Nov 2016 21:03:45 +0530 Subject: [PATCH 1/4] CRM-19585, fixed calculation for default contribution amount price set ---------------------------------------- * CRM-19585: Sales tax issue https://issues.civicrm.org/jira/browse/CRM-19585 --- CRM/Price/BAO/PriceField.php | 6 ++++-- CRM/Price/BAO/PriceSet.php | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CRM/Price/BAO/PriceField.php b/CRM/Price/BAO/PriceField.php index f0e76e896cf7..9fac7a489895 100644 --- a/CRM/Price/BAO/PriceField.php +++ b/CRM/Price/BAO/PriceField.php @@ -590,11 +590,13 @@ public static function addQuickFormElement( * Include inactive options. * @param bool $reset * Discard stored values. + * @param bool $isDefaultContributionPriceSet + * Discard tax amount calculation for price set = default_contribution_amount. * * @return array * array of options */ - public static function getOptions($fieldId, $inactiveNeeded = FALSE, $reset = FALSE) { + public static function getOptions($fieldId, $inactiveNeeded = FALSE, $reset = FALSE, $isDefaultContributionPriceSet = FALSE) { static $options = array(); if ($reset) { $options = array(); @@ -613,7 +615,7 @@ public static function getOptions($fieldId, $inactiveNeeded = FALSE, $reset = FA // ToDo - Code for Hook Invoke foreach ($options[$fieldId] as $priceFieldId => $priceFieldValues) { - if (isset($priceFieldValues['financial_type_id']) && array_key_exists($priceFieldValues['financial_type_id'], $taxRates)) { + 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']); $options[$fieldId][$priceFieldId]['tax_amount'] = $taxAmount['tax_amount']; diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php index 83f7c51467ce..396c8e111de0 100644 --- a/CRM/Price/BAO/PriceSet.php +++ b/CRM/Price/BAO/PriceSet.php @@ -570,6 +570,11 @@ public static function getSetDetail($setID, $required = TRUE, $validOnly = FALSE $dao = CRM_Core_DAO::executeQuery($sql, $params); + $isDefaultContributionPriceSet = FALSE; + if ('default_contribution_amount' == CRM_Core_DAO::getFieldValue('CRM_Price_DAO_PriceSet', $setID)) { + $isDefaultContributionPriceSet = TRUE; + } + $visibility = CRM_Core_PseudoConstant::visibility('name'); while ($dao->fetch()) { $fieldID = $dao->id; @@ -587,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); + $setTree[$setID]['fields'][$fieldID]['options'] = CRM_Price_BAO_PriceField::getOptions($fieldID, FALSE, FALSE, $isDefaultContributionPriceSet); } // also get the pre and post help from this price set From 83e1baa3b8ce181eb35cdc9485d51d80e42857ce Mon Sep 17 00:00:00 2001 From: Pradeep Nayak Date: Mon, 31 Oct 2016 17:38:09 +0530 Subject: [PATCH 2/4] CRM-19585, fixed code for storing civicrm_contribution.tax_amount correctly ---------------------------------------- * CRM-19585: Sales tax issue https://issues.civicrm.org/jira/browse/CRM-19585 --- CRM/Price/BAO/PriceSet.php | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php index 396c8e111de0..52d5b112c158 100644 --- a/CRM/Price/BAO/PriceSet.php +++ b/CRM/Price/BAO/PriceSet.php @@ -803,20 +803,19 @@ public static function processAmount($fields, &$params, &$lineItem, $component = $firstOption = reset($field['options']); $params["price_{$id}"] = array($firstOption['id'] => $params["price_{$id}"]); CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem); - if (CRM_Utils_Array::value('tax_rate', $field['options'][key($field['options'])])) { - $lineItem = self::setLineItem($field, $lineItem, key($field['options'])); - $totalTax += $field['options'][key($field['options'])]['tax_amount'] * $lineItem[key($field['options'])]['qty']; - } - if (CRM_Utils_Array::value('name', $field['options'][key($field['options'])]) == 'contribution_amount') { + $optionValueId = key($field['options']); + + if (CRM_Utils_Array::value('name', $field['options'][$optionValueId]) == 'contribution_amount') { $taxRates = CRM_Core_PseudoConstant::getTaxRates(); if (array_key_exists($params['financial_type_id'], $taxRates)) { $field['options'][key($field['options'])]['tax_rate'] = $taxRates[$params['financial_type_id']]; - $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($field['options'][key($field['options'])]['amount'], $field['options'][key($field['options'])]['tax_rate']); - $field['options'][key($field['options'])]['tax_amount'] = round($taxAmount['tax_amount'], 2); - $lineItem = self::setLineItem($field, $lineItem, key($field['options'])); - $totalTax += $field['options'][key($field['options'])]['tax_amount'] * $lineItem[key($field['options'])]['qty']; + $taxAmount = CRM_Contribute_BAO_Contribution_Utils::calculateTaxAmount($field['options'][$optionValueId]['amount'], $field['options'][$optionValueId]['tax_rate']); + $field['options'][$optionValueId]['tax_amount'] = round($taxAmount['tax_amount'], 2); } } + if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionValueId])) { + $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); + } $totalPrice += $lineItem[$firstOption['id']]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[key($field['options'])]); break; @@ -830,8 +829,7 @@ public static function processAmount($fields, &$params, &$lineItem, $component = CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem, $amount_override); if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionValueId])) { - $lineItem = self::setLineItem($field, $lineItem, $optionValueId); - $totalTax += $field['options'][$optionValueId]['tax_amount']; + $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); if (CRM_Utils_Array::value('field_title', $lineItem[$optionValueId]) == 'Membership Amount') { $lineItem[$optionValueId]['line_total'] = $lineItem[$optionValueId]['unit_price'] = CRM_Utils_Rule::cleanMoney($lineItem[$optionValueId]['line_total'] - $lineItem[$optionValueId]['tax_amount']); } @@ -854,8 +852,7 @@ public static function processAmount($fields, &$params, &$lineItem, $component = CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem); if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionValueId])) { - $lineItem = self::setLineItem($field, $lineItem, $optionValueId); - $totalTax += $field['options'][$optionValueId]['tax_amount']; + $lineItem = self::setLineItem($field, $lineItem, $optionValueId, $totalTax); } $totalPrice += $lineItem[$optionValueId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionValueId]); if ( @@ -872,8 +869,7 @@ public static function processAmount($fields, &$params, &$lineItem, $component = CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem); foreach ($params["price_{$id}"] as $optionId => $option) { if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionId])) { - $lineItem = self::setLineItem($field, $lineItem, $optionId); - $totalTax += $field['options'][$optionId]['tax_amount']; + $lineItem = self::setLineItem($field, $lineItem, $optionId, $totalTax); } $totalPrice += $lineItem[$optionId]['line_total'] + CRM_Utils_Array::value('tax_amount', $lineItem[$optionId]); if ( @@ -1665,10 +1661,11 @@ public static function copyPriceSet($baoName, $id, $newId) { * @param array $field * @param array $lineItem * @param int $optionValueId + * @param float $totalTax * * @return array */ - public static function setLineItem($field, $lineItem, $optionValueId) { + public static function setLineItem($field, $lineItem, $optionValueId, &$totalTax) { if ($field['html_type'] == 'Text') { $taxAmount = $field['options'][$optionValueId]['tax_amount'] * $lineItem[$optionValueId]['qty']; } @@ -1678,7 +1675,7 @@ public static function setLineItem($field, $lineItem, $optionValueId) { $taxRate = $field['options'][$optionValueId]['tax_rate']; $lineItem[$optionValueId]['tax_amount'] = $taxAmount; $lineItem[$optionValueId]['tax_rate'] = $taxRate; - + $totalTax += $taxAmount; return $lineItem; } From 7a1f3919e29343546382af9f76720b88e6260479 Mon Sep 17 00:00:00 2001 From: Pradeep Nayak Date: Thu, 29 Dec 2016 04:50:16 +0530 Subject: [PATCH 3/4] CRM-19585, added test ---------------------------------------- * CRM-19585: Sales tax issue https://issues.civicrm.org/jira/browse/CRM-19585 --- .../CRM/Contribute/Form/ContributionTest.php | 35 +++++++++++++++++++ tests/phpunit/CiviTest/CiviUnitTestCase.php | 26 ++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php index 6face9658257..e903d82463a1 100644 --- a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php +++ b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php @@ -775,4 +775,39 @@ protected function getCreditCardParams() { ); } + /** + * Test the submit function for FT with tax. + */ + public function testSubmitSaleTax() { + $this->enableTaxAndInvoicing(); + $this->relationForFinancialTypeWithFinancialAccount($this->_financialTypeId); + $form = new CRM_Contribute_Form_Contribution(); + + $form->testSubmit(array( + 'total_amount' => 100, + 'financial_type_id' => $this->_financialTypeId, + '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' => 0, + ), + CRM_Core_Action::ADD + ); + $contribution = $this->callAPISuccessGetSingle('Contribution', + array( + 'contact_id' => $this->_individualId, + 'return' => array('tax_amount', 'total_amount'), + ) + ); + $this->assertEquals(110, $contribution['total_amount']); + $this->assertEquals(10, $contribution['tax_amount']); + $this->callAPISuccessGetCount('FinancialTrxn', array(), 1); + $this->callAPISuccessGetCount('FinancialItem', array(), 2); + $lineItem = $this->callAPISuccessGetSingle('LineItem', array('contribution_id' => $contribution['id'])); + $this->assertEquals(100, $lineItem['line_total']); + $this->assertEquals(10, $lineItem['tax_amount']); + } + } diff --git a/tests/phpunit/CiviTest/CiviUnitTestCase.php b/tests/phpunit/CiviTest/CiviUnitTestCase.php index bb661a2ef878..296dc5ec7d3b 100644 --- a/tests/phpunit/CiviTest/CiviUnitTestCase.php +++ b/tests/phpunit/CiviTest/CiviUnitTestCase.php @@ -3650,6 +3650,32 @@ protected function enableTaxAndInvoicing($params = array()) { return Civi::settings()->set('contribution_invoice_settings', $contributeSetting); } + /** + * Add Sales Tax relation for financial type with financial account. + * + * @param int $financialTypeId + * + * @return obj + */ + protected function relationForFinancialTypeWithFinancialAccount($financialTypeId) { + $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, + 'is_active' => 1, + ); + $account = CRM_Financial_BAO_FinancialAccount::add($params); + $entityParams = array( + 'entity_table' => 'civicrm_financial_type', + 'account_relationship' => key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Sales Tax Account is' ")), + 'entity_id' => $financialTypeId, + 'financial_account_id' => $account->id, + ); + return CRM_Financial_BAO_FinancialTypeAccount::add($entityParams); + } + /** * Create price set with contribution test for test setup. * From 1ec04220ef891d1fa83d0b0e40d1a642d5c0165e Mon Sep 17 00:00:00 2001 From: Pradeep Nayak Date: Thu, 29 Dec 2016 04:50:40 +0530 Subject: [PATCH 4/4] CRM-19585, added test ---------------------------------------- * CRM-19585: Sales tax issue https://issues.civicrm.org/jira/browse/CRM-19585 --- .../CRM/Contribute/Form/ContributionTest.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php index e903d82463a1..0f0e6d69efee 100644 --- a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php +++ b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php @@ -810,4 +810,45 @@ public function testSubmitSaleTax() { $this->assertEquals(10, $lineItem['tax_amount']); } + /** + * Test the submit function for FT without tax. + */ + public function testSubmitWithOutSaleTax() { + $this->enableTaxAndInvoicing(); + $this->relationForFinancialTypeWithFinancialAccount($this->_financialTypeId); + $form = new CRM_Contribute_Form_Contribution(); + + $form->testSubmit(array( + 'total_amount' => 100, + 'financial_type_id' => 3, + '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' => 0, + ), + CRM_Core_Action::ADD + ); + $contribution = $this->callAPISuccessGetSingle('Contribution', + array( + 'contact_id' => $this->_individualId, + 'return' => array('tax_amount', 'total_amount'), + ) + ); + $this->assertEquals(100, $contribution['total_amount']); + $this->assertEquals(NULL, $contribution['tax_amount']); + $this->callAPISuccessGetCount('FinancialTrxn', array(), 1); + $this->callAPISuccessGetCount('FinancialItem', array(), 1); + $lineItem = $this->callAPISuccessGetSingle( + 'LineItem', + array( + 'contribution_id' => $contribution['id'], + 'return' => array('line_total', 'tax_amount'), + ) + ); + $this->assertEquals(100, $lineItem['line_total']); + $this->assertTrue(empty($lineItem['tax_amount'])); + } + }