/** * 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); if ($this->_helper->isCrossBorderTradeEnabled($this->_store)) { $this->_areTaxRequestsSimilar = true; } else { $this->_areTaxRequestsSimilar = $this->_calculator->compareRequests($storeRequest, $addressRequest); } } foreach ($items as $item) { if ($item->getParentItem()) { continue; } if ($item->getHasChildren() && $item->isChildrenCalculated()) { foreach ($item->getChildren() as $child) { $this->_processItem($child, $addressRequest); } $this->_recalculateParent($item); } else { $this->_processItem($item, $addressRequest); } $this->_addSubtotalAmount($address, $item); } $address->setRoundingDeltas($this->_roundingDeltas); return $this; }
/** * Calculate the Weee tax based on the discount and rate * * @param float $rate * @param Mage_Sales_Model_Quote_Item_Abstract $item * @param float $discountAmount * @param float $weeeAmountIncludingTax * @param float $weeeAmountExclTax * @return mixed */ private function _getWeeeTax($rate, $item, $discountAmount, $weeeAmountIncludingTax, $weeeAmountExclTax) { $isWeeeTaxAlreadyIncluded = $this->_weeeHelper->isTaxIncluded($this->_store); $sameRateAsStore = $this->_helper->isCrossBorderTradeEnabled($this->_store) || $rate == $this->_calculator->getStoreRateForItem($item); if ($sameRateAsStore && $isWeeeTaxAlreadyIncluded) { if (!$discountAmount || $discountAmount <= 0) { //We want to skip the re calculation and return the difference return max($weeeAmountIncludingTax - $weeeAmountExclTax, 0); } else { return $this->_calculator->calcTaxAmount($weeeAmountIncludingTax - $discountAmount, $rate, true, true); } } $discountAmount = !$discountAmount ? 0 : $discountAmount; ///Regular case where weee does not have the tax and we want to calculate the tax return $this->_calculator->calcTaxAmount($weeeAmountExclTax - $discountAmount, $rate, false, true); }
/** * Get Weee amounts associated with a product * * @param Mage_Catalog_Model_Product $product * @param Mage_Customer_Model_Address_Abstract $shipping * @param Mage_Customer_Model_Address_Abstract $billing * @param mixed $website * @param boolean $calculateTax * @param boolean $ignoreDiscount * @return array|\Varien_Object */ public function getProductWeeeAttributes($product, $shipping = null, $billing = null, $website = null, $calculateTax = null, $ignoreDiscount = false) { $result = array(); $allWeee = $this->getWeeeTaxAttributeCodes(); if (!$allWeee) { return $result; } $websiteId = Mage::app()->getWebsite($website)->getId(); $store = Mage::app()->getWebsite($website)->getDefaultGroup()->getDefaultStore(); $customer = null; if ($shipping) { $customerTaxClass = $shipping->getQuote()->getCustomerTaxClassId(); $customer = $shipping->getQuote()->getCustomer(); } else { $customerTaxClass = null; } $calculator = Mage::getModel('tax/calculation'); if ($customer) { $calculator->setCustomer($customer); } $rateRequest = $calculator->getRateRequest($shipping, $billing, $customerTaxClass, $store); $currentPercent = $product->getTaxPercent(); if (!$currentPercent) { $currentPercent = Mage::getSingleton('tax/calculation')->getRate($rateRequest->setProductClassId($product->getTaxClassId())); } $discountPercent = 0; if (!$ignoreDiscount && Mage::helper('weee')->isDiscounted($store)) { $discountPercent = $this->_getDiscountPercentForProduct($product); } $productAttributes = $product->getTypeInstance(true)->getSetAttributes($product); foreach ($productAttributes as $code => $attribute) { if (in_array($code, $allWeee)) { $attributeSelect = $this->getResource()->getReadConnection()->select(); $attributeSelect->from($this->getResource()->getTable('weee/tax'), 'value')->where('attribute_id = ?', (int) $attribute->getId())->where('website_id IN(?)', array($websiteId, 0))->where('country = ?', $rateRequest->getCountryId())->where('state IN(?)', array($rateRequest->getRegionId(), '*'))->where('entity_id = ?', (int) $product->getId())->limit(1); $order = array('state ' . Varien_Db_Select::SQL_DESC, 'website_id ' . Varien_Db_Select::SQL_DESC); $attributeSelect->order($order); $value = $this->getResource()->getReadConnection()->fetchOne($attributeSelect); if ($value) { if ($discountPercent) { $value = Mage::app()->getStore()->roundPrice($value - $value * $discountPercent / 100); } $taxAmount = 0; $amount = $value; if ($calculateTax && Mage::helper('weee')->isTaxable($store)) { if ($this->_taxHelper->isCrossBorderTradeEnabled($store)) { $defaultPercent = $currentPercent; } else { $defaultRateRequest = $calculator->getDefaultRateRequest($store); $defaultPercent = Mage::getModel('tax/calculation')->getRate($defaultRateRequest->setProductClassId($product->getTaxClassId())); } if (Mage::helper('weee')->isTaxIncluded($store)) { $taxAmount = Mage::app()->getStore()->roundPrice($value / (100 + $defaultPercent) * $currentPercent); $amount = $amount - $taxAmount; } else { $appliedRates = Mage::getModel('tax/calculation')->getAppliedRates($rateRequest); if (count($appliedRates) > 1) { $taxAmount = 0; foreach ($appliedRates as $appliedRate) { $taxRate = $appliedRate['percent']; $taxAmount += Mage::app()->getStore()->roundPrice($value * $taxRate / 100); } } else { $taxAmount = Mage::app()->getStore()->roundPrice($value * $currentPercent / 100); } } } $one = new Varien_Object(); $one->setName(Mage::helper('catalog')->__($attribute->getFrontend()->getLabel()))->setAmount($amount)->setTaxAmount($taxAmount)->setCode($attribute->getAttributeCode()); $result[] = $one; } } } return $result; }
/** * Return the default rate request. It can be either based on store address or customer address * * @param type $store * @return \Varien_Object */ public function getDefaultRateRequest($store = null) { if ($this->_taxHelper->isCrossBorderTradeEnabled($store)) { //If cross border trade is enabled, we will use customer tax rate as store tax rate return $this->getRateRequest(null, null, null, $store); } else { return $this->getRateOriginRequest($store); } }
/** * Collect totals information about shipping * * @param Mage_Sales_Model_Quote_Address $address * @return Mage_Sales_Model_Quote_Address_Total_Shipping */ public function collect(Mage_Sales_Model_Quote_Address $address) { parent::collect($address); $calc = $this->_calculator; $store = $address->getQuote()->getStore(); $storeTaxRequest = $calc->getRateOriginRequest($store); $addressTaxRequest = $calc->getRateRequest($address, $address->getQuote()->getBillingAddress(), $address->getQuote()->getCustomerTaxClassId(), $store); $shippingTaxClass = $this->_config->getShippingTaxClass($store); $storeTaxRequest->setProductClassId($shippingTaxClass); $addressTaxRequest->setProductClassId($shippingTaxClass); $priceIncludesTax = $this->_config->shippingPriceIncludesTax($store); if ($priceIncludesTax) { if ($this->_helper->isCrossBorderTradeEnabled($store)) { $this->_areTaxRequestsSimilar = true; } else { $this->_areTaxRequestsSimilar = $this->_calculator->compareRequests($storeTaxRequest, $addressTaxRequest); } } $shipping = $taxShipping = $address->getShippingAmount(); $baseShipping = $baseTaxShipping = $address->getBaseShippingAmount(); $rate = $calc->getRate($addressTaxRequest); if ($priceIncludesTax) { if ($this->_areTaxRequestsSimilar) { $tax = $this->_round($calc->calcTaxAmount($shipping, $rate, true, false), $rate, true); $baseTax = $this->_round($calc->calcTaxAmount($baseShipping, $rate, true, false), $rate, true, 'base'); $taxShipping = $shipping; $baseTaxShipping = $baseShipping; $shipping = $shipping - $tax; $baseShipping = $baseShipping - $baseTax; $taxable = $taxShipping; $baseTaxable = $baseTaxShipping; $isPriceInclTax = true; $address->setTotalAmount('shipping', $shipping); $address->setBaseTotalAmount('shipping', $baseShipping); } else { $storeRate = $calc->getStoreRate($addressTaxRequest, $store); $storeTax = $calc->calcTaxAmount($shipping, $storeRate, true, false); $baseStoreTax = $calc->calcTaxAmount($baseShipping, $storeRate, true, false); $shipping = $calc->round($shipping - $storeTax); $baseShipping = $calc->round($baseShipping - $baseStoreTax); $tax = $this->_round($calc->calcTaxAmount($shipping, $rate, false, false), $rate, true); $baseTax = $this->_round($calc->calcTaxAmount($baseShipping, $rate, false, false), $rate, true, 'base'); $taxShipping = $shipping + $tax; $baseTaxShipping = $baseShipping + $baseTax; $taxable = $taxShipping; $baseTaxable = $baseTaxShipping; $isPriceInclTax = true; $address->setTotalAmount('shipping', $shipping); $address->setBaseTotalAmount('shipping', $baseShipping); } } else { $appliedRates = $calc->getAppliedRates($addressTaxRequest); $taxes = array(); $baseTaxes = array(); foreach ($appliedRates as $appliedRate) { $taxRate = $appliedRate['percent']; $taxId = $appliedRate['id']; $taxes[] = $this->_round($calc->calcTaxAmount($shipping, $taxRate, false, false), $taxId, false); $baseTaxes[] = $this->_round($calc->calcTaxAmount($baseShipping, $taxRate, false, false), $taxId, false, 'base'); } $tax = array_sum($taxes); $baseTax = array_sum($baseTaxes); $taxShipping = $shipping + $tax; $baseTaxShipping = $baseShipping + $baseTax; $taxable = $shipping; $baseTaxable = $baseShipping; $isPriceInclTax = false; $address->setTotalAmount('shipping', $shipping); $address->setBaseTotalAmount('shipping', $baseShipping); } $address->setShippingInclTax($taxShipping); $address->setBaseShippingInclTax($baseTaxShipping); $address->setShippingTaxable($taxable); $address->setBaseShippingTaxable($baseTaxable); $address->setIsShippingInclTax($isPriceInclTax); if ($this->_config->discountTax($store)) { $address->setShippingAmountForDiscount($taxShipping); $address->setBaseShippingAmountForDiscount($baseTaxShipping); } return $this; }