/**
  * 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);
 }
Exemple #3
0
 /**
  * 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;
 }
Exemple #4
0
 /**
  * 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);
     }
 }
Exemple #5
0
 /**
  * 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;
 }