From dc42816109244d2b73dcbea4881c49a3f65bb884 Mon Sep 17 00:00:00 2001 From: dpradeep Date: Thu, 22 May 2014 10:00:06 +0530 Subject: [PATCH] VAT-365 Proposed Tax UI changes --- CRM/Contribute/Form/Contribution/Main.php | 8 +- CRM/Core/PseudoConstant.php | 40 +++++++++ CRM/Price/BAO/PriceField.php | 102 ++++++++++++++++++++-- CRM/Price/BAO/PriceSet.php | 39 ++++++++- templates/CRM/Price/Form/PriceSet.tpl | 17 +++- 5 files changed, 196 insertions(+), 10 deletions(-) diff --git a/CRM/Contribute/Form/Contribution/Main.php b/CRM/Contribute/Form/Contribution/Main.php index 24dbec05ad..f220a0007a 100644 --- a/CRM/Contribute/Form/Contribution/Main.php +++ b/CRM/Contribute/Form/Contribution/Main.php @@ -1230,10 +1230,16 @@ class CRM_Contribute_Form_Contribution_Main extends CRM_Contribute_Form_Contribu $component = 'membership'; } CRM_Price_BAO_PriceSet::processAmount($this->_values['fee'], $params, $lineItem[$priceSetId], $component); + if ($params['tax_amount']) { + $this->set('tax_amount', $params['tax_amount']); + } if ($proceFieldAmount) { - $lineItem[$params['priceSetId']][$fieldOption]['line_total'] = $proceFieldAmount; $lineItem[$params['priceSetId']][$fieldOption]['unit_price'] = $proceFieldAmount; + if (isset($lineItem[$params['priceSetId']][$fieldOption]['tax_amount'])) { + $proceFieldAmount += $lineItem[$params['priceSetId']][$fieldOption]['tax_amount']; + } + $lineItem[$params['priceSetId']][$fieldOption]['line_total'] = $proceFieldAmount; if (!$this->_membershipBlock['is_separate_payment']) { $params['amount'] = $proceFieldAmount; //require when separate membership not used } diff --git a/CRM/Core/PseudoConstant.php b/CRM/Core/PseudoConstant.php index 7d333fa87f..86515b84a9 100644 --- a/CRM/Core/PseudoConstant.php +++ b/CRM/Core/PseudoConstant.php @@ -202,6 +202,13 @@ class CRM_Core_PseudoConstant { */ private static $accountOptionValues; + /** + * Tax Rates + * @var array + * @static + */ + private static $taxRates; + /** * Low-level option getter, rarely accessed directly. * NOTE: Rather than calling this function directly use CRM_*_BAO_*::buildOptions() @@ -1827,5 +1834,38 @@ WHERE id = %1 public static function getModuleExtensions($fresh = FALSE) { return CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles($fresh); } + + + /** + * Get all tax rates + * + * The static array tax rates is returned + * + * @access public + * @static + * + * @return array - array list of tax rates with the financial type + */ + public static function getTaxRates() { + if (!self::$taxRates) { + self::$taxRates = array(); + $sql = " + SELECT fa.tax_rate, efa.entity_id + FROM civicrm_entity_financial_account efa + INNER JOIN civicrm_financial_account fa ON fa.id = efa.financial_account_id + INNER JOIN civicrm_option_value cov ON cov.value = efa.account_relationship + INNER JOIN civicrm_option_group cog ON cog.id = cov.option_group_id + WHERE efa.entity_table = 'civicrm_financial_type' + AND cov.name = 'Sales Tax Account is' + AND cog.name = 'account_relationship' + AND fa.is_active = 1"; + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + self::$taxRates[$dao->entity_id] = $dao->tax_rate; + } + } + + return self::$taxRates; + } } diff --git a/CRM/Price/BAO/PriceField.php b/CRM/Price/BAO/PriceField.php index a029dd1494..e9a45d77a7 100644 --- a/CRM/Price/BAO/PriceField.php +++ b/CRM/Price/BAO/PriceField.php @@ -283,12 +283,19 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField { //use value field. $valueFieldName = 'amount'; $seperator = '|'; + $displayOpt = CRM_Contribute_BAO_Contribution::getContributionSettings(); + $displayOpt = $displayOpt['tax_display_settings']; switch ($field->html_type) { case 'Text': $optionKey = key($customOption); $count = CRM_Utils_Array::value('count', $customOption[$optionKey], ''); $max_value = CRM_Utils_Array::value('max_value', $customOption[$optionKey], ''); - $priceVal = implode($seperator, array($customOption[$optionKey][$valueFieldName], $count, $max_value)); + $taxAmount = 0; + if (CRM_Utils_Array::value('tax_amount', $customOption[$optionKey])) { + $taxAmount = $customOption[$optionKey]['tax_amount']; + $qf->assign('displayOpt', $displayOpt); + } + $priceVal = implode($seperator, array($customOption[$optionKey][$valueFieldName] + $taxAmount, $count, $max_value)); $extra = array(); if (!empty($qf->_quickConfig) && !empty($qf->_contributionAmount)) { @@ -346,13 +353,30 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField { } foreach ($customOption as $opId => $opt) { + $taxAmount = 0; if ($field->is_display_amounts) { $opt['label'] = !empty($opt['label']) ? $opt['label'] : ''; - $opt['label'] = '' . CRM_Utils_Money::format($opt[$valueFieldName]) . ' ' . $opt['label'] . ''; + if (CRM_Utils_Array::value('tax_amount', $opt)) { + $taxAmount = $opt['tax_amount']; + if ($displayOpt == 'Do_not_show') { + $opt['label'] = '' . CRM_Utils_Money::format($opt[$valueFieldName] + $taxAmount) . ' ' . $opt['label'] . ''; + } + else if ($displayOpt == 'Inclusive') { + $opt['label'] = '' . CRM_Utils_Money::format($opt[$valueFieldName] + $taxAmount) . ' ' . $opt['label'] . ''; + $opt['label'] .= ' (includes '.round($opt['tax_rate'],2).'% VAT - ' . CRM_Utils_Money::format($taxAmount) . ')'; + } + else { + $opt['label'] = '' . CRM_Utils_Money::format($opt[$valueFieldName]) . ' ' . $opt['label'] . ''; + $opt['label'] .= ' + '.round($opt['tax_rate'],2).'% VAT - ' . CRM_Utils_Money::format($taxAmount) . ''; + } + } + else { + $opt['label'] = '' . CRM_Utils_Money::format($opt[$valueFieldName]) . ' ' . $opt['label'] . ''; + } } $count = CRM_Utils_Array::value('count', $opt, ''); $max_value = CRM_Utils_Array::value('max_value', $opt, ''); - $priceVal = implode($seperator, array($opt[$valueFieldName], $count, $max_value)); + $priceVal = implode($seperator, array($opt[$valueFieldName] + $taxAmount, $count, $max_value)); $extra = array('price' => json_encode(array($elementName, $priceVal)), 'data-amount' => $opt[$valueFieldName], 'data-currency' => $currencyName, @@ -421,15 +445,32 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField { $selectOption = $allowedOptions = $priceVal = array(); foreach ($customOption as $opt) { + $taxAmount = 0; $count = CRM_Utils_Array::value('count', $opt, ''); $max_value = CRM_Utils_Array::value('max_value', $opt, ''); - $priceVal[$opt['id']] = implode($seperator, array($opt[$valueFieldName], $count, $max_value)); if ($field->is_display_amounts) { $opt['label'] .= ' - '; - $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName]); + if (CRM_Utils_Array::value('tax_amount', $opt)) { + $taxAmount = $opt['tax_amount']; + if ($displayOpt == 'Do_not_show') { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName] + $taxAmount); + } + else if ($displayOpt == 'Inclusive') { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName] + $taxAmount); + $opt['label'] .= ' (includes '.round($opt['tax_rate'],2).'% VAT - ' . CRM_Utils_Money::format($taxAmount) . ')'; + } + else { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName]); + $opt['label'] .= ' + '.round($opt['tax_rate'],2).'% VAT - ' . CRM_Utils_Money::format($taxAmount) . ''; + } + } + else { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName]); + } } $selectOption[$opt['id']] = $opt['label']; + $priceVal[$opt['id']] = implode($seperator, array($opt[$valueFieldName] + $taxAmount, $count, $max_value)); if (!in_array($opt['id'], $feezeOptions)) { $allowedOptions[] = $opt['id']; @@ -456,14 +497,31 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField { $check = array(); foreach ($customOption as $opId => $opt) { + $taxAmount = 0; $count = CRM_Utils_Array::value('count', $opt, ''); $max_value = CRM_Utils_Array::value('max_value', $opt, ''); - $priceVal = implode($seperator, array($opt[$valueFieldName], $count, $max_value)); if ($field->is_display_amounts) { $opt['label'] .= ' - '; - $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName]); + if (CRM_Utils_Array::value('tax_amount', $opt)) { + $taxAmount = $opt['tax_amount']; + if ($displayOpt == 'Do_not_show') { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName] + $taxAmount); + } + else if ($displayOpt == 'Inclusive') { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName] + $taxAmount); + $opt['label'] .= ' (includes '.round($opt['tax_rate'],2).'% VAT - ' . CRM_Utils_Money::format($taxAmount) . ')'; + } + else { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName]); + $opt['label'] .= ' + '.round($opt['tax_rate'],2).'% VAT - ' . CRM_Utils_Money::format($taxAmount) . ''; + } + } + else { + $opt['label'] .= CRM_Utils_Money::format($opt[$valueFieldName]); + } } + $priceVal = implode($seperator, array($opt[$valueFieldName] + $taxAmount, $count, $max_value)); $check[$opId] = &$qf->createElement('checkbox', $opt['id'], NULL, $opt['label'], array('price' => json_encode(array($opt['id'], $priceVal)), 'data-amount' => $opt[$valueFieldName], @@ -506,6 +564,17 @@ class CRM_Price_BAO_PriceField extends CRM_Price_DAO_PriceField { $values = array(); CRM_Price_BAO_PriceFieldValue::getValues($fieldId, $values, 'weight', !$inactiveNeeded); $options[$fieldId] = $values; + $taxRates = CRM_Core_PseudoConstant::getTaxRates(); + + // ToDo - Code for Hook Invoke + + foreach ($options[$fieldId] as $priceFieldId => $priceFieldValues) { + if (array_key_exists($priceFieldValues['financial_type_id'], $taxRates)) { + $options[$fieldId][$priceFieldId]['tax_rate'] = $taxRates[$priceFieldValues['financial_type_id']]; + $taxAmount = self::calculateTaxAmount($priceFieldValues['amount'], $options[$fieldId][$priceFieldId]['tax_rate']); + $options[$fieldId][$priceFieldId]['tax_amount'] = round($taxAmount['tax_amount'],2); + } + } } return $options[$fieldId]; @@ -679,5 +748,24 @@ WHERE id IN (" . implode(',', array_keys($priceFields)) . ')'; } } } + + /** + * Calculate the tax amount based on given tax rate. + * + * @param float $amount amount of field. + * @param float $taxRate tax rate of selected financial account for field. + * + * @return array array of tax amount + * + * @access public + * @static + * + */ + public static function calculateTaxAmount($amount, $taxRate) { + $taxAmount = array(); + $taxAmount['tax_amount'] = ($taxRate/100) * $amount; + + return $taxAmount; + } } diff --git a/CRM/Price/BAO/PriceSet.php b/CRM/Price/BAO/PriceSet.php index 3457fc57da..567603c4fb 100644 --- a/CRM/Price/BAO/PriceSet.php +++ b/CRM/Price/BAO/PriceSet.php @@ -653,7 +653,7 @@ WHERE id = %1"; static function processAmount(&$fields, &$params, &$lineItem, $component = '') { // using price set - $totalPrice = 0; + $totalPrice = $totalTax = 0; $radioLevel = $checkboxLevel = $selectLevel = $textLevel = array(); if ($component) { $autoRenew = array(); @@ -671,6 +671,10 @@ WHERE id = %1"; case 'Text': $params["price_{$id}"] = array(key($field['options']) => $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']; + } $totalPrice += $lineItem[key($field['options'])]['line_total']; break; @@ -693,6 +697,10 @@ WHERE id = %1"; $radioLevel = array_keys($params['amount_priceset_level_radio']); } 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']; + } $totalPrice += $lineItem[$optionValueId]['line_total']; if ( $component && @@ -718,6 +726,10 @@ WHERE id = %1"; $selectLevel = array_keys($params['amount_priceset_level_select']); } 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']; + } $totalPrice += $lineItem[$optionValueId]['line_total']; if ( $component && @@ -747,6 +759,10 @@ WHERE id = %1"; } CRM_Price_BAO_LineItem::format($id, $params, $field, $lineItem); foreach ($optionIds as $optionId) { + if (CRM_Utils_Array::value('tax_rate', $field['options'][$optionId])) { + $lineItem = self::setLineItem($field, $lineItem, $optionId); + $totalTax += $field['options'][$optionId]['tax_amount']; + } $totalPrice += $lineItem[$optionId]['line_total']; if ( $component && @@ -779,6 +795,7 @@ WHERE id = %1"; } $params['amount_level'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $amount_level) . $displayParticipantCount . CRM_Core_DAO::VALUE_SEPARATOR; $params['amount'] = $totalPrice; + $params['tax_amount'] = $totalTax; if ($component) { foreach ($autoRenew as $dontCare => $eachAmount) { if (!$eachAmount) { @@ -1257,5 +1274,25 @@ WHERE ps.id = %1 } } } + + /* + * Function to set tax_amount and tax_rate in LineItem + * + * + */ + static function setLineItem($field, $lineItem, $optionValueId) { + if ($field['html_type'] == 'Text') { + $taxAmount = $field['options'][$optionValueId]['tax_amount'] * $lineItem[$optionValueId]['qty']; + } + else { + $taxAmount = $field['options'][$optionValueId]['tax_amount']; + } + $taxRate = $field['options'][$optionValueId]['tax_rate']; + $lineItem[$optionValueId]['line_total'] = $lineItem[$optionValueId]['line_total'] + $taxAmount; + $lineItem[$optionValueId]['tax_amount'] = $taxAmount; + $lineItem[$optionValueId]['tax_rate'] = $taxRate; + + return $lineItem; + } } diff --git a/templates/CRM/Price/Form/PriceSet.tpl b/templates/CRM/Price/Form/PriceSet.tpl index a345302937..3e160917db 100644 --- a/templates/CRM/Price/Form/PriceSet.tpl +++ b/templates/CRM/Price/Form/PriceSet.tpl @@ -70,7 +70,22 @@
{$form.$element_name.html} {if $element.is_display_amounts && $element.html_type eq 'Text'} - {foreach item=option from=$element.options}{$option.amount|crmMoney}{/foreach} + {foreach item=option from=$element.options} + {if $option.tax_amount && $displayOpt} + {assign var="amount" value=`$option.amount+$option.tax_amount`} + {if $displayOpt == 'Do_not_show'} + {$amount|crmMoney} + {elseif $displayOpt == 'Inclusive'} + {$amount|crmMoney} + (includes {$option.tax_rate|round:2}% VAT - {$option.tax_amount|crmMoney}) + {else} + {$option.amount|crmMoney} + + {$option.tax_rate|round:2}% VAT - {$option.tax_amount|crmMoney} + {/if} + {else} + {$option.amount|crmMoney} + {/if} + {/foreach} {/if} {if $element.help_post}
{$element.help_post}{/if} -- 2.25.1