Created
December 18, 2012 12:49
-
-
Save pkdavies/4327682 to your computer and use it in GitHub Desktop.
Magento rounding issue patch file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git app/code/core/Mage/Core/Model/Store.php app/code/core/Mage/Core/Model/Store.php | |
index 66a94f5..1a146a5 100644 | |
--- app/code/core/Mage/Core/Model/Store.php | |
+++ app/code/core/Mage/Core/Model/Store.php | |
@@ -106,6 +106,12 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract | |
*/ | |
const MEDIA_REWRITE_SCRIPT = 'get.php/'; | |
+ | |
+ /** | |
+ * Rounding Epsilon | |
+ */ | |
+ const ROUNDING_EPSILON = 1e-7; | |
+ | |
/** | |
* Cache flag | |
* | |
@@ -941,7 +947,19 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract | |
*/ | |
public function roundPrice($price) | |
{ | |
- return round($price, 2); | |
+ return $this->roundEpsilon($price, 6); | |
+ } | |
+ | |
+ /** | |
+ * Round price through epsilon | |
+ * | |
+ * @param mixed $price | |
+ * @param int $precision | |
+ * @return double | |
+ */ | |
+ public function roundEpsilon($price, $precision = 2) | |
+ { | |
+ return round($price + self::ROUNDING_EPSILON, (int) $precision); | |
} | |
/** | |
diff --git app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Shipping.php app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Shipping.php | |
index 358957d..375a5d3 100644 | |
--- app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Shipping.php | |
+++ app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Shipping.php | |
@@ -63,7 +63,7 @@ class Mage_Sales_Model_Order_Creditmemo_Total_Shipping extends Mage_Sales_Model_ | |
* Shipping refund amount shouldn't cause errors, if it doesn't exceed that limit. | |
* Note: ($x < $y + 0.0001) means ($x <= $y) for floats | |
*/ | |
- if ($baseShippingAmount < Mage::app()->getStore()->roundPrice($baseAllowedAmount) + 0.0001) { | |
+ if ($baseShippingAmount < Mage::app()->getStore()->roundEpsilon($baseAllowedAmount) + 0.0001) { | |
/* | |
* Shipping refund amount should be equated to allowed refund amount, | |
* if it exceeds that limit. | |
diff --git app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php | |
index 30367ec..ba7949d 100644 | |
--- app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php | |
+++ app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php | |
@@ -161,6 +161,9 @@ class Mage_Sales_Model_Order_Creditmemo_Total_Tax extends Mage_Sales_Model_Order | |
$creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $totalTax + $totalHiddenTax); | |
$creditmemo->setBaseGrandTotal($creditmemo->getBaseGrandTotal() + $baseTotalTax + $baseTotalHiddenTax); | |
+ | |
+ $creditmemo->setShippingAmount(Mage::app()->getStore()->roundEpsilon($creditmemo->getShippingAmount())); | |
+ $creditmemo->setBaseShippingAmount(Mage::app()->getStore()->roundEpsilon($creditmemo->getBaseShippingAmount())); | |
return $this; | |
} | |
} | |
diff --git app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php | |
index d72dc17..38cfc00 100644 | |
--- app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php | |
+++ app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php | |
@@ -324,8 +324,8 @@ class Mage_Tax_Model_Sales_Total_Quote_Subtotal extends Mage_Sales_Model_Quote_A | |
$baseTaxPrice = $basePrice; | |
$taxSubtotal = $subtotal; | |
$baseTaxSubtotal= $baseSubtotal; | |
- $subtotal = $this->_calculator->round($subtotal - $rowTax); | |
- $baseSubtotal = $this->_calculator->round($baseSubtotal - $baseRowTax); | |
+ $subtotal = $subtotal - $this->_calculator->round($rowTax); | |
+ $baseSubtotal = $baseSubtotal - $this->_calculator->round($baseRowTax); | |
$price = $this->_calculator->round($subtotal/$qty); | |
$basePrice = $this->_calculator->round($baseSubtotal/$qty); | |
if ($taxOnOrigPrice) { | |
@@ -340,8 +340,8 @@ class Mage_Tax_Model_Sales_Total_Quote_Subtotal extends Mage_Sales_Model_Quote_A | |
$storeRate = $this->_calculator->getStoreRate($request, $this->_store); | |
$storeTax = $this->_calculator->calcTaxAmount($subtotal, $storeRate, true, false); | |
$baseStoreTax = $this->_calculator->calcTaxAmount($baseSubtotal, $storeRate, true, false); | |
- $subtotal = $this->_calculator->round($subtotal - $storeTax); | |
- $baseSubtotal = $this->_calculator->round($baseSubtotal - $baseStoreTax); | |
+ $subtotal = $subtotal - $this->_calculator->round($storeTax); | |
+ $baseSubtotal = $baseSubtotal - $this->_calculator->round($baseStoreTax); | |
$price = $this->_calculator->round($subtotal/$qty); | |
$basePrice = $this->_calculator->round($baseSubtotal/$qty); | |
@@ -352,8 +352,8 @@ class Mage_Tax_Model_Sales_Total_Quote_Subtotal extends Mage_Sales_Model_Quote_A | |
$taxPrice = $this->_calculator->round($taxSubtotal/$qty); | |
$baseTaxPrice = $this->_calculator->round($baseTaxSubtotal/$qty); | |
if ($taxOnOrigPrice) { | |
- $taxable = $this->_calculator->round($origSubtotal - $storeTax); | |
- $baseTaxable = $this->_calculator->round($baseOrigSubtotal - $baseStoreTax); | |
+ $taxable = $origSubtotal - $this->_calculator->round($storeTax); | |
+ $baseTaxable = $baseOrigSubtotal - $this->_calculator->round($baseStoreTax); | |
} else { | |
$taxable = $subtotal; | |
$baseTaxable = $baseSubtotal; | |
diff --git app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php | |
index b91ee46..92a13b5 100644 | |
--- app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php | |
+++ app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php | |
@@ -376,23 +376,67 @@ class Mage_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Addres | |
$baseUnitTax = $this->_calculator->calcTaxAmount($basePrice, $rate, $inclTax); | |
break; | |
case Mage_Tax_Model_Calculation::CALC_TAX_AFTER_DISCOUNT_ON_EXCL: | |
- case Mage_Tax_Model_Calculation::CALC_TAX_AFTER_DISCOUNT_ON_INCL: | |
$discountAmount = $item->getDiscountAmount() / $qty; | |
$baseDiscountAmount = $item->getBaseDiscountAmount() / $qty; | |
$unitTax = $this->_calculator->calcTaxAmount($price, $rate, $inclTax); | |
- $discountRate = ($unitTax/$price) * 100; | |
- $unitTaxDiscount = $this->_calculator->calcTaxAmount($discountAmount, $discountRate, $inclTax, false); | |
+ $unitTaxDiscount = $this->_calculator->calcTaxAmount($discountAmount, $rate, $inclTax, false); | |
$unitTax = max($unitTax - $unitTaxDiscount, 0); | |
$baseUnitTax = $this->_calculator->calcTaxAmount($basePrice, $rate, $inclTax); | |
- $baseDiscountRate = ($baseUnitTax/$basePrice) * 100; | |
$baseUnitTaxDiscount = $this->_calculator | |
- ->calcTaxAmount($baseDiscountAmount, $baseDiscountRate, $inclTax, false); | |
+ ->calcTaxAmount($baseDiscountAmount, $rate, $inclTax, false); | |
$baseUnitTax = max($baseUnitTax - $baseUnitTaxDiscount, 0); | |
if ($inclTax && $discountAmount > 0) { | |
- $hiddenTax = $this->_calculator->calcTaxAmount($discountAmount, $rate, $inclTax, false); | |
- $baseHiddenTax = $this->_calculator->calcTaxAmount($baseDiscountAmount, $rate, $inclTax, false); | |
+ $amount = $unitTax ? $discountAmount : $price; | |
+ $hiddenTax = $this->_calculator->calcTaxAmount($amount, $rate, $inclTax, false); | |
+ | |
+ $baseAmount = $baseUnitTax ? $baseDiscountAmount : $basePrice; | |
+ $baseHiddenTax = $this->_calculator->calcTaxAmount($baseAmount, $rate, $inclTax, false); | |
+ | |
+ $this->_hiddenTaxes[] = array( | |
+ 'rate_key' => $rateKey, | |
+ 'qty' => $qty, | |
+ 'item' => $item, | |
+ 'value' => $hiddenTax, | |
+ 'base_value' => $baseHiddenTax, | |
+ 'incl_tax' => $inclTax, | |
+ ); | |
+ } elseif ($discountAmount > $price) { // case with 100% discount on price incl. tax | |
+ $hiddenTax = $discountAmount - $price; | |
+ $baseHiddenTax = $baseDiscountAmount - $basePrice; | |
+ $this->_hiddenTaxes[] = array( | |
+ 'rate_key' => $rateKey, | |
+ 'qty' => $qty, | |
+ 'item' => $item, | |
+ 'value' => $hiddenTax, | |
+ 'base_value' => $baseHiddenTax, | |
+ 'incl_tax' => $inclTax, | |
+ ); | |
+ } | |
+ break; | |
+ case Mage_Tax_Model_Calculation::CALC_TAX_AFTER_DISCOUNT_ON_INCL: | |
+ $discountAmount = $item->getDiscountAmount() / $qty; | |
+ $baseDiscountAmount = $item->getBaseDiscountAmount() / $qty; | |
+ | |
+ $unitTax = $this->_calculator->calcTaxAmount( | |
+ max($price - $discountAmount, 0), | |
+ $rate, | |
+ $inclTax | |
+ ); | |
+ $baseUnitTax = $this->_calculator->calcTaxAmount( | |
+ max($basePrice - $baseDiscountAmount, 0), | |
+ $rate, | |
+ $inclTax | |
+ ); | |
+ | |
+ if ($inclTax && $discountAmount > 0) { | |
+ $amount = $unitTax ? $discountAmount : $price; | |
+ $hiddenTax = $this->_calculator->calcTaxAmount($amount, $rate, $inclTax, false); | |
+ | |
+ $baseAmount = $baseUnitTax ? $baseDiscountAmount : $basePrice; | |
+ $baseHiddenTax = $this->_calculator->calcTaxAmount($baseAmount, $rate, $inclTax, false); | |
+ | |
$this->_hiddenTaxes[] = array( | |
'rate_key' => $rateKey, | |
'qty' => $qty, | |
@@ -457,8 +501,7 @@ class Mage_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Addres | |
$child->setTaxRates($applied); | |
} | |
$this->_recalculateParent($item); | |
- } | |
- else { | |
+ } else { | |
$taxRateRequest->setProductClassId($item->getProduct()->getTaxClassId()); | |
$rate = $this->_calculator->getRate($taxRateRequest); | |
$this->_calcRowTaxAmount($item, $rate); | |
@@ -524,8 +567,12 @@ class Mage_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Addres | |
$inclTax | |
); | |
if ($inclTax && $discountAmount > 0) { | |
- $hiddenTax = $this->_calculator->calcTaxAmount($discountAmount, $rate, $inclTax, false); | |
- $baseHiddenTax = $this->_calculator->calcTaxAmount($baseDiscountAmount, $rate, $inclTax, false); | |
+ $amount = $rowTax ? $discountAmount : $subtotal; | |
+ $hiddenTax = $this->_calculator->calcTaxAmount($amount, $rate, $inclTax, false); | |
+ | |
+ $baseAmount = $rowTax ? $baseDiscountAmount : $baseSubtotal; | |
+ $baseHiddenTax = $this->_calculator->calcTaxAmount($baseAmount, $rate, $inclTax, false); | |
+ | |
$this->_hiddenTaxes[] = array( | |
'rate_key' => $rateKey, | |
'qty' => 1, | |
@@ -658,7 +705,7 @@ class Mage_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Addres | |
$baseTaxSubtotal = max($baseSubtotal - $baseDiscount, 0); | |
$rowTax = $this->_calculator->calcTaxAmount($taxSubtotal, $rate, $inclTax, false); | |
$baseRowTax = $this->_calculator->calcTaxAmount($baseTaxSubtotal, $rate, $inclTax, false); | |
- if (!$item->getNoDiscount() && $item->getWeeeTaxApplied()) { | |
+ if (!$item->getNoDiscount() && $item->getWeeeTaxAppliedAmount()) { | |
$rowTaxBeforeDiscount = $this->_calculator->calcTaxAmount( | |
$subtotal, | |
$rate, | |
@@ -674,8 +721,12 @@ class Mage_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Addres | |
} | |
if ($inclTax && $discount > 0) { | |
- $hiddenTax = $this->_calculator->calcTaxAmount($discount, $rate, $inclTax, false); | |
- $baseHiddenTax = $this->_calculator->calcTaxAmount($baseDiscount, $rate, $inclTax, false); | |
+ $amount = $this->_calculator->round($rowTax) ? $discount : $subtotal; | |
+ $hiddenTax = $this->_calculator->calcTaxAmount($amount, $rate, $inclTax, false); | |
+ | |
+ $baseAmount = $this->_calculator->round($baseRowTax) ? $baseDiscount : $baseSubtotal; | |
+ $baseHiddenTax = $this->_calculator->calcTaxAmount($baseAmount, $rate, $inclTax, false); | |
+ | |
$this->_hiddenTaxes[] = array( | |
'rate_key' => $rateKey, | |
'qty' => 1, |
Discovered this introduces a rounding down issue on products i.e. 2x £2.50 = £4.99
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
action in public_html directory with:
patch -p0 < SUPEE-662_EE_1.12.0.2_v2.patch