Skip to content

Instantly share code, notes, and snippets.

@pkdavies
Created December 18, 2012 12:49
Show Gist options
  • Save pkdavies/4327682 to your computer and use it in GitHub Desktop.
Save pkdavies/4327682 to your computer and use it in GitHub Desktop.
Magento rounding issue patch file
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,
@pkdavies
Copy link
Author

action in public_html directory with:

patch -p0 < SUPEE-662_EE_1.12.0.2_v2.patch

@pkdavies
Copy link
Author

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