/** * Collect address subtotal * * @param Mage_Sales_Model_Quote_Address $address * @return Mage_Sales_Model_Quote_Address_Total_Subtotal */ public function collect(Mage_Sales_Model_Quote_Address $address) { if ($address->getAddressType() == 'billing') { return $this; } $juros = Mage::getSingleton('checkout/session')->getJuros(); $address->setBaseJurosAmount($juros); $address->setJurosAmount($juros); $address->setBaseTotalAmount($this->getCode(), $juros); $address->setTotalAmount($this->getCode(), $juros); return $this; }
/** * Add row total item amount to subtotal * * @param Mage_Sales_Model_Quote_Address $address * @param Mage_Sales_Model_Quote_Item_Abstract $item * * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal */ protected function _addSubtotalAmount(Mage_Sales_Model_Quote_Address $address, $item) { if ($this->_config->priceIncludesTax($this->_store)) { $subTotal = $item->getRowTotalInclTax() - $item->getRowTax(); $baseSubTotal = $item->getBaseRowTotalInclTax() - $item->getBaseRowTax(); $address->setTotalAmount('subtotal', $address->getTotalAmount('subtotal') + $subTotal); $address->setBaseTotalAmount('subtotal', $address->getBaseTotalAmount('subtotal') + $baseSubTotal); } else { $address->setTotalAmount('subtotal', $address->getTotalAmount('subtotal') + $item->getRowTotal()); $address->setBaseTotalAmount('subtotal', $address->getBaseTotalAmount('subtotal') + $item->getBaseRowTotal()); } $address->setSubtotalInclTax($address->getSubtotalInclTax() + $item->getRowTotalInclTax()); $address->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax() + $item->getBaseRowTotalInclTax()); return $this; }
/** * Calculate item price including/excluding tax, row total including/excluding tax * and subtotal including/excluding tax. * Determine discount price if needed * * @param Mage_Sales_Model_Quote_Address $address * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal */ public function collect(Mage_Sales_Model_Quote_Address $address) { $this->_store = $address->getQuote()->getStore(); $this->_address = $address; $this->_subtotalInclTax = 0; $this->_baseSubtotalInclTax = 0; $this->_subtotal = 0; $this->_baseSubtotal = 0; $this->_roundingDeltas = array(); $address->setSubtotalInclTax(0); $address->setBaseSubtotalInclTax(0); $address->setTotalAmount('subtotal', 0); $address->setBaseTotalAmount('subtotal', 0); $items = $this->_getAddressItems($address); if (!$items) { return $this; } $addressRequest = $this->_getAddressTaxRequest($address); $storeRequest = $this->_getStoreTaxRequest($address); $this->_calculator->setCustomer($address->getQuote()->getCustomer()); if ($this->_config->priceIncludesTax($this->_store)) { $classIds = array(); foreach ($items as $item) { $classIds[] = $item->getProduct()->getTaxClassId(); if ($item->getHasChildren()) { foreach ($item->getChildren() as $child) { $classIds[] = $child->getProduct()->getTaxClassId(); } } } $classIds = array_unique($classIds); $storeRequest->setProductClassId($classIds); $addressRequest->setProductClassId($classIds); $this->_areTaxRequestsSimilar = $this->_calculator->compareRequests($storeRequest, $addressRequest); } foreach ($items as $item) { if ($item->getParentItem()) { continue; } $origItem = clone $item; if ($item->getHasChildren() && $item->isChildrenCalculated()) { foreach ($item->getChildren() as $child) { $this->_processItem($child, $addressRequest); if ($child->getTaxPercent() > 0) { $item->setTaxPercent($child->getTaxPercent()); } } $this->_recalculateParent($item); } else { $this->_processItem($item, $addressRequest); } if ($origItem->getCustomPrice()) { $taxPercent = $item->getTaxPercent(); $customPrice = $origItem->getCustomPrice(); $price = $customPrice; $taxAmount = $customPrice * ($taxPercent / 100); $baseTaxAmount = $customPrice * ($taxPercent / 100); $basePrice = $customPrice; $rowTotal = $customPrice * $item->getQty(); $baseRowTotal = $customPrice * $item->getQty(); $priceInclTax = $customPrice + $taxAmount; $basePriceInclTax = $customPrice + $baseTaxAmount; $rowTotalInclTax = $priceInclTax * $item->getQty(); $baseRowTotalInclTax = $basePriceInclTax * $item->getQty(); $item->setCustomPrice($origItem->getCustomPrice()); $item->setConvertedPrice($price); $item->setPrice($basePrice); $item->setRowTotal($rowTotal); $item->setBaseRowTotal($baseRowTotal); $item->setTaxableAmount($rowTotal); $item->setBaseTaxableAmount($baseRowTotal); $item->setPriceInclTax($priceInclTax); $item->setBasePriceInclTax($basePriceInclTax); $item->setRowTotalInclTax($rowTotalInclTax); $item->setBaseRowTotalInclTax($baseRowTotalInclTax); $count = 0; if ($item->getHasChildren()) { foreach ($item->getChildren() as $child) { if ($count === 0) { $child->setTaxableAmount($rowTotal); $child->setBaseTaxableAmount($baseRowTotal); } else { $child->setTaxableAmount(0); $child->setBaseTaxableAmount(0); } $count++; } } } $this->_addSubtotalAmount($address, $item); } $address->setRoundingDeltas($this->_roundingDeltas); return $this; }
/** * Round the total amounts in address * * @param Mage_Sales_Model_Quote_Address $address * @return Mage_Tax_Model_Sales_Total_Quote_Tax */ protected function _roundTotals(Mage_Sales_Model_Quote_Address $address) { // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5 $totalDelta = 1.0E-6; $baseTotalDelta = 1.0E-6; /* * The order of rounding is import here. * Tax is rounded first, to be consistent with unit based calculation. * Hidden tax and shipping_hidden_tax are rounded next, which are really part of tax. * Shipping is rounded before subtotal to minimize the chance that subtotal is * rounded differently because of the delta. * Here is an example: 19.2% tax rate, subtotal = 49.95, shipping = 9.99, discount = 20% * subtotalExclTax = 41.90436, tax = 7.7238, hidden_tax = 1.609128, shippingPriceExclTax = 8.38087 * shipping_hidden_tax = 0.321826, discount = -11.988 * The grand total is 47.952 ~= 47.95 * The rounded values are: * tax = 7.72, hidden_tax = 1.61, shipping_hidden_tax = 0.32, * shipping = 8.39 (instead of 8.38 from simple rounding), subtotal = 41.9, discount = -11.99 * The grand total calculated from the rounded value is 47.95 * If we simply round each value and add them up, the result is 47.94, which is one penny off */ $totalCodes = array('tax', 'hidden_tax', 'shipping_hidden_tax', 'shipping', 'subtotal', 'weee', 'discount'); foreach ($totalCodes as $totalCode) { $exactAmount = $address->getTotalAmount($totalCode); $baseExactAmount = $address->getBaseTotalAmount($totalCode); if (!$exactAmount && !$baseExactAmount) { continue; } $roundedAmount = $this->_calculator->round($exactAmount + $totalDelta); $baseRoundedAmount = $this->_calculator->round($baseExactAmount + $baseTotalDelta); $address->setTotalAmount($totalCode, $roundedAmount); $address->setBaseTotalAmount($totalCode, $baseRoundedAmount); $totalDelta = $exactAmount + $totalDelta - $roundedAmount; $baseTotalDelta = $baseExactAmount + $baseTotalDelta - $baseRoundedAmount; } return $this; }
/** * Add row total item amount to subtotal * * @param Mage_Sales_Model_Quote_Address $address * @param Mage_Sales_Model_Quote_Item_Abstract $item * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal */ protected function _addSubtotalAmount(Mage_Sales_Model_Quote_Address $address, $item) { $address->setTotalAmount('subtotal', $address->getTotalAmount('subtotal') + $item->getRowTotal()); $address->setBaseTotalAmount('subtotal', $address->getBaseTotalAmount('subtotal') + $item->getBaseRowTotal()); $address->setSubtotalInclTax($address->getSubtotalInclTax() + $item->getRowTotalInclTax()); $address->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax() + $item->getBaseRowTotalInclTax()); return $this; }
/** * Tax caclulation for shipping price * * @param Mage_Sales_Model_Quote_Address $address * @param Varien_Object $taxRateRequest * @return Mage_Tax_Model_Sales_Total_Quote */ protected function _calculateShippingTax(Mage_Sales_Model_Quote_Address $address, $taxRateRequest) { $store = $address->getQuote()->getStore(); $shippingTaxClass = $this->_config->getShippingTaxClass($store); $shippingAmount = $address->getShippingAmount(); $baseShippingAmount = $address->getBaseShippingAmount(); $shippingDiscountAmount = $address->getShippingDiscountAmount(); $baseShippingDiscountAmount = $address->getBaseShippingDiscountAmount(); /** * Subtract discount before calculate tax amount */ if ($this->_config->applyTaxAfterDiscount($store)) { $calcAmount = $shippingAmount - $shippingDiscountAmount; $baseCalcAmount = $baseShippingAmount - $baseShippingDiscountAmount; } else { $calcAmount = $shippingAmount; $baseCalcAmount = $baseShippingAmount; } $shippingTax = 0; $shippingBaseTax = 0; if ($shippingTaxClass) { $taxRateRequest->setProductClassId($shippingTaxClass); $rate = $this->_calculator->getRate($taxRateRequest); if ($rate) { if ($this->_config->shippingPriceIncludesTax($store) && $this->_areTaxRequestsSimilar) { $shippingTax = $this->_calculator->calcTaxAmount($calcAmount, $rate, true, false); $shippingBaseTax = $this->_calculator->calcTaxAmount($baseCalcAmount, $rate, true, false); $shippingAmount -= $shippingTax; $baseShippingAmount -= $shippingBaseTax; } else { $shippingTax = $this->_calculator->calcTaxAmount($calcAmount, $rate, false, false); $shippingBaseTax = $this->_calculator->calcTaxAmount($baseCalcAmount, $rate, false, false); } $rateKey = (string) $rate; if (isset($this->_roundingDeltas[$rateKey])) { $shippingTax += $this->_roundingDeltas[$rateKey]; } if (isset($this->_baseRoundingDeltas[$rateKey])) { $shippingBaseTax += $this->_baseRoundingDeltas[$rateKey]; } $shippingTax = $this->_calculator->round($shippingTax); $shippingBaseTax = $this->_calculator->round($shippingBaseTax); $address->setTotalAmount('shipping', $shippingAmount); $address->setBaseTotalAmount('shipping', $baseShippingAmount); /** * Provide additional attributes for apply discount on price include tax */ if ($this->_config->discountTax($store)) { $address->setShippingAmountForDiscount($shippingAmount + $shippingTax); $address->setBaseShippingAmountForDiscount($baseShippingAmount + $shippingBaseTax); } $this->_addAmount($shippingTax); $this->_addBaseAmount($shippingBaseTax); $applied = $this->_calculator->getAppliedRates($taxRateRequest); $this->_saveAppliedTaxes($address, $applied, $shippingTax, $shippingBaseTax, $rate); } } $address->setShippingTaxAmount($shippingTax); $address->setBaseShippingTaxAmount($shippingBaseTax); return $this; }