Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_Tax_Block_Adminhtml_Frontend_Region_Updater
  • Mage_Tax_Block_Checkout_Discount
  • Mage_Tax_Block_Checkout_Grandtotal
  • Mage_Tax_Block_Checkout_Shipping
  • Mage_Tax_Block_Checkout_Subtotal
  • Mage_Tax_Block_Checkout_Tax
  • Mage_Tax_Block_Sales_Order_Tax
  • Mage_Tax_Helper_Data
  • Mage_Tax_Model_Calculation
  • Mage_Tax_Model_Calculation_Rate
  • Mage_Tax_Model_Calculation_Rate_Title
  • Mage_Tax_Model_Calculation_Rule
  • Mage_Tax_Model_Class
  • Mage_Tax_Model_Class_Source_Customer
  • Mage_Tax_Model_Class_Source_Product
  • Mage_Tax_Model_Config
  • Mage_Tax_Model_Config_Price_Include
  • Mage_Tax_Model_Mysql4_Calculation
  • Mage_Tax_Model_Mysql4_Calculation_Collection
  • Mage_Tax_Model_Mysql4_Calculation_Rate
  • Mage_Tax_Model_Mysql4_Calculation_Rate_Collection
  • Mage_Tax_Model_Mysql4_Calculation_Rate_Title
  • Mage_Tax_Model_Mysql4_Calculation_Rate_Title_Collection
  • Mage_Tax_Model_Mysql4_Calculation_Rule
  • Mage_Tax_Model_Mysql4_Calculation_Rule_Collection
  • Mage_Tax_Model_Mysql4_Class
  • Mage_Tax_Model_Mysql4_Class_Collection
  • Mage_Tax_Model_Mysql4_Report_Collection
  • Mage_Tax_Model_Mysql4_Report_Tax
  • Mage_Tax_Model_Mysql4_Report_Updatedat_Collection
  • Mage_Tax_Model_Mysql4_Sales_Order_Tax
  • Mage_Tax_Model_Mysql4_Sales_Order_Tax_Collection
  • Mage_Tax_Model_Mysql4_Setup
  • Mage_Tax_Model_Observer
  • Mage_Tax_Model_Resource_Calculation
  • Mage_Tax_Model_Resource_Calculation_Collection
  • Mage_Tax_Model_Resource_Calculation_Rate
  • Mage_Tax_Model_Resource_Calculation_Rate_Collection
  • Mage_Tax_Model_Resource_Calculation_Rate_Title
  • Mage_Tax_Model_Resource_Calculation_Rate_Title_Collection
  • Mage_Tax_Model_Resource_Calculation_Rule
  • Mage_Tax_Model_Resource_Calculation_Rule_Collection
  • Mage_Tax_Model_Resource_Class
  • Mage_Tax_Model_Resource_Class_Collection
  • Mage_Tax_Model_Resource_Report_Collection
  • Mage_Tax_Model_Resource_Report_Tax
  • Mage_Tax_Model_Resource_Report_Tax_Createdat
  • Mage_Tax_Model_Resource_Report_Tax_Updatedat
  • Mage_Tax_Model_Resource_Report_Updatedat_Collection
  • Mage_Tax_Model_Resource_Sales_Order_Tax
  • Mage_Tax_Model_Resource_Sales_Order_Tax_Collection
  • Mage_Tax_Model_Resource_Sales_Order_Tax_Item
  • Mage_Tax_Model_Resource_Sales_Order_Tax_Item_Collection
  • Mage_Tax_Model_Resource_Setup
  • Mage_Tax_Model_Sales_Order_Tax
  • Mage_Tax_Model_Sales_Order_Tax_Item
  • Mage_Tax_Model_Sales_Pdf_Grandtotal
  • Mage_Tax_Model_Sales_Pdf_Shipping
  • Mage_Tax_Model_Sales_Pdf_Subtotal
  • Mage_Tax_Model_Sales_Pdf_Tax
  • Mage_Tax_Model_Sales_Total_Quote_Discount
  • Mage_Tax_Model_Sales_Total_Quote_Nominal_Subtotal
  • Mage_Tax_Model_Sales_Total_Quote_Nominal_Tax
  • Mage_Tax_Model_Sales_Total_Quote_Shipping
  • Mage_Tax_Model_Sales_Total_Quote_Subtotal
  • Mage_Tax_Model_Sales_Total_Quote_Tax
  • Mage_Tax_Model_System_Config_Source_Algorithm
  • Mage_Tax_Model_System_Config_Source_Apply
  • Mage_Tax_Model_System_Config_Source_PriceType
  • Mage_Tax_Model_System_Config_Source_Tax_Country
  • Mage_Tax_Model_System_Config_Source_Tax_Display_Type
  • Mage_Tax_Model_System_Config_Source_Tax_Region

Exceptions

  • Mage_Tax_Exception
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Magento
  4:  *
  5:  * NOTICE OF LICENSE
  6:  *
  7:  * This source file is subject to the Open Software License (OSL 3.0)
  8:  * that is bundled with this package in the file LICENSE.txt.
  9:  * It is also available through the world-wide-web at this URL:
 10:  * http://opensource.org/licenses/osl-3.0.php
 11:  * If you did not receive a copy of the license and are unable to
 12:  * obtain it through the world-wide-web, please send an email
 13:  * to license@magentocommerce.com so we can send you a copy immediately.
 14:  *
 15:  * DISCLAIMER
 16:  *
 17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
 18:  * versions in the future. If you wish to customize Magento for your
 19:  * needs please refer to http://www.magentocommerce.com for more information.
 20:  *
 21:  * @category    Mage
 22:  * @package     Mage_Tax
 23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
 24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 25:  */
 26: 
 27: /**
 28:  * Calculate items and address amounts including/excluding tax
 29:  */
 30: class Mage_Tax_Model_Sales_Total_Quote_Subtotal extends Mage_Sales_Model_Quote_Address_Total_Abstract
 31: {
 32:     /**
 33:      * Tax calculation model
 34:      *
 35:      * @var Mage_Tax_Model_Calculation
 36:      */
 37:     protected $_calculator = null;
 38: 
 39:     /**
 40:      * Tax configuration object
 41:      *
 42:      * @var Mage_Tax_Model_Config
 43:      */
 44:     protected $_config = null;
 45:     protected $_helper = null;
 46: 
 47:     protected $_subtotalInclTax     = 0;
 48:     protected $_baseSubtotalInclTax = 0;
 49:     protected $_subtotal            = 0;
 50:     protected $_baseSubtotal        = 0;
 51: 
 52:     /**
 53:      * Flag which is initialized when collect method is started and catalog prices include tax.
 54:      * Is used for checking if store tax and customer tax requests are similar
 55:      *
 56:      * @var bool
 57:      */
 58:     protected $_areTaxRequestsSimilar = false;
 59: 
 60:     /**
 61:      * Request which can be used for tax rate calculation
 62:      *
 63:      * @var Varien_Object
 64:      */
 65:     protected $_storeTaxRequest = null;
 66: 
 67:     /**
 68:      *  Quote store
 69:      *
 70:      * @var Mage_Core_Model_Store
 71:      */
 72:     protected $_store;
 73: 
 74:     /**
 75:      * Rounding deltas for prices
 76:      *
 77:      * @var array
 78:      */
 79:     protected $_roundingDeltas = array();
 80: 
 81:     /**
 82:      * Class constructor
 83:      */
 84:     public function __construct()
 85:     {
 86:         $this->setCode('tax_subtotal');
 87:         $this->_helper      = Mage::helper('tax');
 88:         $this->_calculator  = Mage::getSingleton('tax/calculation');
 89:         $this->_config      = Mage::getSingleton('tax/config');
 90:     }
 91: 
 92:     /**
 93:      * Calculate item price including/excluding tax, row total including/excluding tax
 94:      * and subtotal including/excluding tax.
 95:      * Determine discount price if needed
 96:      *
 97:      * @param   Mage_Sales_Model_Quote_Address $address
 98:      * @return  Mage_Tax_Model_Sales_Total_Quote_Subtotal
 99:      */
100:     public function collect(Mage_Sales_Model_Quote_Address $address)
101:     {
102:         $this->_store   = $address->getQuote()->getStore();
103:         $this->_address = $address;
104: 
105:         $this->_subtotalInclTax     = 0;
106:         $this->_baseSubtotalInclTax = 0;
107:         $this->_subtotal            = 0;
108:         $this->_baseSubtotal        = 0;
109:         $this->_roundingDeltas      = array();
110: 
111:         $address->setSubtotalInclTax(0);
112:         $address->setBaseSubtotalInclTax(0);
113:         $address->setTotalAmount('subtotal', 0);
114:         $address->setBaseTotalAmount('subtotal', 0);
115: 
116:         $items = $this->_getAddressItems($address);
117:         if (!$items) {
118:             return $this;
119:         }
120: 
121:         $addressRequest = $this->_getAddressTaxRequest($address);
122:         $storeRequest   = $this->_getStoreTaxRequest($address);
123:         $this->_calculator->setCustomer($address->getQuote()->getCustomer());
124:         if ($this->_config->priceIncludesTax($this->_store)) {
125:             $classIds = array();
126:             foreach ($items as $item) {
127:                 $classIds[] = $item->getProduct()->getTaxClassId();
128:                 if ($item->getHasChildren()) {
129:                     foreach ($item->getChildren() as $child) {
130:                         $classIds[] = $child->getProduct()->getTaxClassId();
131:                     }
132:                 }
133:             }
134:             $classIds = array_unique($classIds);
135:             $storeRequest->setProductClassId($classIds);
136:             $addressRequest->setProductClassId($classIds);
137:             $this->_areTaxRequestsSimilar = $this->_calculator->compareRequests($storeRequest, $addressRequest);
138:         }
139: 
140:         foreach ($items as $item) {
141:             if ($item->getParentItem()) {
142:                 continue;
143:             }
144:             if ($item->getHasChildren() && $item->isChildrenCalculated()) {
145:                 foreach ($item->getChildren() as $child) {
146:                     $this->_processItem($child, $addressRequest);
147:                 }
148:                 $this->_recalculateParent($item);
149:             } else {
150:                 $this->_processItem($item, $addressRequest);
151:             }
152:             $this->_addSubtotalAmount($address, $item);
153:         }
154:         $address->setRoundingDeltas($this->_roundingDeltas);
155:         return $this;
156:     }
157: 
158:     /**
159:      * Caclulate item price and row total with configured rounding level
160:      *
161:      * @param Mage_Sales_Model_Quote_Address $address
162:      * @param Mage_Sales_Model_Quote_Item_Abstract $item
163:      * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal
164:      */
165:     protected function _processItem($item, $taxRequest)
166:     {
167:         switch ($this->_config->getAlgorithm($this->_store)) {
168:             case Mage_Tax_Model_Calculation::CALC_UNIT_BASE:
169:                 $this->_unitBaseCalculation($item, $taxRequest);
170:                 break;
171:             case Mage_Tax_Model_Calculation::CALC_ROW_BASE:
172:                 $this->_rowBaseCalculation($item, $taxRequest);
173:                 break;
174:             case Mage_Tax_Model_Calculation::CALC_TOTAL_BASE:
175:                 $this->_totalBaseCalculation($item, $taxRequest);
176:                 break;
177:             default:
178:                 break;
179:         }
180:         return $this;
181:     }
182: 
183:     /**
184:      * Calculate item price and row total including/excluding tax based on unit price rounding level
185:      *
186:      * @param Mage_Sales_Model_Quote_Item_Abstract $item
187:      * @param Varien_Object $request
188:      * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal
189:      */
190:     protected function _unitBaseCalculation($item, $request)
191:     {
192:         $request->setProductClassId($item->getProduct()->getTaxClassId());
193:         $rate   = $this->_calculator->getRate($request);
194:         $qty    = $item->getTotalQty();
195: 
196:         $price          = $taxPrice         = $item->getCalculationPriceOriginal();
197:         $basePrice      = $baseTaxPrice     = $item->getBaseCalculationPriceOriginal();
198:         $subtotal       = $taxSubtotal      = $item->getRowTotal();
199:         $baseSubtotal   = $baseTaxSubtotal  = $item->getBaseRowTotal();
200:         $taxOnOrigPrice = !$this->_helper->applyTaxOnCustomPrice($this->_store) && $item->hasCustomPrice();
201:         if ($taxOnOrigPrice) {
202:             $origPrice       = $item->getOriginalPrice();
203:             $baseOrigPrice   = $item->getBaseOriginalPrice();
204:         }
205: 
206: 
207:         $item->setTaxPercent($rate);
208:         if ($this->_config->priceIncludesTax($this->_store)) {
209:             if ($this->_sameRateAsStore($request)) {
210:                 $tax            = $this->_calculator->calcTaxAmount($price, $rate, true);
211:                 $baseTax        = $this->_calculator->calcTaxAmount($basePrice, $rate, true);
212:                 $taxPrice       = $price;
213:                 $baseTaxPrice   = $basePrice;
214:                 $taxSubtotal    = $subtotal;
215:                 $baseTaxSubtotal= $baseSubtotal;
216:                 $price          = $price - $tax;
217:                 $basePrice      = $basePrice - $baseTax;
218:                 $subtotal       = $price * $qty;
219:                 $baseSubtotal   = $basePrice * $qty;
220:                 if ($taxOnOrigPrice) {
221:                     $taxable        = $origPrice;
222:                     $baseTaxable    = $baseOrigPrice;
223:                 } else {
224:                     $taxable        = $taxPrice;
225:                     $baseTaxable    = $baseTaxPrice;
226:                 }
227:                 $isPriceInclTax = true;
228:             } else {
229:                 $storeRate      = $this->_calculator->getStoreRate($request, $this->_store);
230:                 $storeTax       = $this->_calculator->calcTaxAmount($price, $storeRate, true);
231:                 $baseStoreTax   = $this->_calculator->calcTaxAmount($basePrice, $storeRate, true);
232:                 $price          = $price - $storeTax;
233:                 $basePrice      = $basePrice - $baseStoreTax;
234:                 $subtotal       = $price * $qty;
235:                 $baseSubtotal   = $basePrice * $qty;
236: 
237:                 $tax            = $this->_calculator->calcTaxAmount($price, $rate, false);
238:                 $baseTax        = $this->_calculator->calcTaxAmount($basePrice, $rate, false);
239:                 $taxPrice       = $price + $tax;
240:                 $baseTaxPrice   = $basePrice + $baseTax;
241:                 $taxSubtotal    = $taxPrice * $qty;
242:                 $baseTaxSubtotal= $baseTaxPrice * $qty;
243:                 if ($taxOnOrigPrice) {
244:                     $taxable        = $origPrice - $storeTax;
245:                     $baseTaxable    = $baseOrigPrice - $baseStoreTax;
246:                 } else {
247:                     $taxable        = $price;
248:                     $baseTaxable    = $basePrice;
249:                 }
250:                 $isPriceInclTax = false;
251:             }
252:         } else {
253:             $tax            = $this->_calculator->calcTaxAmount($price, $rate, false);
254:             $baseTax        = $this->_calculator->calcTaxAmount($basePrice, $rate, false);
255:             $taxPrice       = $price + $tax;
256:             $baseTaxPrice   = $basePrice + $baseTax;
257:             $taxSubtotal    = $taxPrice * $qty;
258:             $baseTaxSubtotal= $baseTaxPrice * $qty;
259:             if ($taxOnOrigPrice) {
260:                 $taxable        = $origPrice;
261:                 $baseTaxable    = $baseOrigPrice;
262:             } else {
263:                 $taxable        = $price;
264:                 $baseTaxable    = $basePrice;
265:             }
266:             $isPriceInclTax = false;
267:         }
268: 
269:         if ($item->hasCustomPrice()) {
270:             /**
271:              * Initialize item original price before declaring custom price
272:              */
273:             $item->getOriginalPrice();
274:             $item->setCustomPrice($price);
275:             $item->setBaseCustomPrice($basePrice);
276:         }
277:         $item->setPrice($basePrice);
278:         $item->setBasePrice($basePrice);
279:         $item->setRowTotal($subtotal);
280:         $item->setBaseRowTotal($baseSubtotal);
281:         $item->setPriceInclTax($taxPrice);
282:         $item->setBasePriceInclTax($baseTaxPrice);
283:         $item->setRowTotalInclTax($taxSubtotal);
284:         $item->setBaseRowTotalInclTax($baseTaxSubtotal);
285:         $item->setTaxableAmount($taxable);
286:         $item->setBaseTaxableAmount($baseTaxable);
287:         $item->setIsPriceInclTax($isPriceInclTax);
288:         if ($this->_config->discountTax($this->_store)) {
289:             $item->setDiscountCalculationPrice($taxPrice);
290:             $item->setBaseDiscountCalculationPrice($baseTaxPrice);
291:         }
292:         return $this;
293:     }
294: 
295:     /**
296:      * Calculate item price and row total including/excluding tax based on row total price rounding level
297:      *
298:      * @param Mage_Sales_Model_Quote_Item_Abstract $item
299:      * @param Varien_Object $request
300:      * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal
301:      */
302:     protected function _rowBaseCalculation($item, $request)
303:     {
304:         $request->setProductClassId($item->getProduct()->getTaxClassId());
305:         $rate   = $this->_calculator->getRate($request);
306:         $qty    = $item->getTotalQty();
307: 
308:         $price          = $taxPrice         = $item->getCalculationPriceOriginal();
309:         $basePrice      = $baseTaxPrice     = $item->getBaseCalculationPriceOriginal();
310:         $subtotal       = $taxSubtotal      = $item->getRowTotal();
311:         $baseSubtotal   = $baseTaxSubtotal  = $item->getBaseRowTotal();
312:         $taxOnOrigPrice = !$this->_helper->applyTaxOnCustomPrice($this->_store) && $item->hasCustomPrice();
313:         if ($taxOnOrigPrice) {
314:             $origSubtotal       = $item->getOriginalPrice() * $qty;
315:             $baseOrigSubtotal   = $item->getBaseOriginalPrice() * $qty;
316:         }
317: 
318:         $item->setTaxPercent($rate);
319:         if ($this->_config->priceIncludesTax($this->_store)) {
320:             if ($this->_sameRateAsStore($request)) {
321:                 $rowTax         = $this->_calculator->calcTaxAmount($subtotal, $rate, true, false);
322:                 $baseRowTax     = $this->_calculator->calcTaxAmount($baseSubtotal, $rate, true, false);
323:                 $taxPrice       = $price;
324:                 $baseTaxPrice   = $basePrice;
325:                 $taxSubtotal    = $subtotal;
326:                 $baseTaxSubtotal= $baseSubtotal;
327:                 $subtotal       = $this->_calculator->round($subtotal - $rowTax);
328:                 $baseSubtotal   = $this->_calculator->round($baseSubtotal - $baseRowTax);
329:                 $price          = $this->_calculator->round($subtotal/$qty);
330:                 $basePrice      = $this->_calculator->round($baseSubtotal/$qty);
331:                 if ($taxOnOrigPrice) {
332:                     $taxable        = $origSubtotal;
333:                     $baseTaxable    = $baseOrigSubtotal;
334:                 } else {
335:                     $taxable        = $taxSubtotal;
336:                     $baseTaxable    = $baseTaxSubtotal;
337:                 }
338:                 $isPriceInclTax = true;
339:             } else {
340:                 $storeRate      = $this->_calculator->getStoreRate($request, $this->_store);
341:                 $storeTax       = $this->_calculator->calcTaxAmount($subtotal, $storeRate, true, false);
342:                 $baseStoreTax   = $this->_calculator->calcTaxAmount($baseSubtotal, $storeRate, true, false);
343:                 $subtotal       = $this->_calculator->round($subtotal - $storeTax);
344:                 $baseSubtotal   = $this->_calculator->round($baseSubtotal - $baseStoreTax);
345:                 $price          = $this->_calculator->round($subtotal/$qty);
346:                 $basePrice      = $this->_calculator->round($baseSubtotal/$qty);
347: 
348:                 $rowTax         = $this->_calculator->calcTaxAmount($subtotal, $rate, false, false);
349:                 $baseRowTax     = $this->_calculator->calcTaxAmount($baseSubtotal, $rate, false, false);
350:                 $taxSubtotal    = $subtotal + $rowTax;
351:                 $baseTaxSubtotal= $baseSubtotal + $baseRowTax;
352:                 $taxPrice       = $this->_calculator->round($taxSubtotal/$qty);
353:                 $baseTaxPrice   = $this->_calculator->round($baseTaxSubtotal/$qty);
354:                 if ($taxOnOrigPrice) {
355:                     $taxable        = $this->_calculator->round($origSubtotal - $storeTax);
356:                     $baseTaxable    = $this->_calculator->round($baseOrigSubtotal - $baseStoreTax);
357:                 } else {
358:                     $taxable        = $subtotal;
359:                     $baseTaxable    = $baseSubtotal;
360:                 }
361:                 $isPriceInclTax = false;
362:             }
363:         } else {
364:             $rowTax     = $this->_calculator->calcTaxAmount($subtotal, $rate, false, false);
365:             $baseRowTax = $this->_calculator->calcTaxAmount($baseSubtotal, $rate, false, false);
366:             $taxSubtotal    = $subtotal + $rowTax;
367:             $baseTaxSubtotal= $baseSubtotal + $baseRowTax;
368:             $taxPrice       = $this->_calculator->round($taxSubtotal/$qty);
369:             $baseTaxPrice   = $this->_calculator->round($baseTaxSubtotal/$qty);
370:             if ($taxOnOrigPrice) {
371:                 $taxable        = $origSubtotal;
372:                 $baseTaxable    = $baseOrigSubtotal;
373:             } else {
374:                 $taxable        = $subtotal;
375:                 $baseTaxable    = $baseSubtotal;
376:             }
377:             $isPriceInclTax = false;
378:         }
379: 
380:         if ($item->hasCustomPrice()) {
381:             /**
382:              * Initialize item original price before declaring custom price
383:              */
384:             $item->getOriginalPrice();
385:             $item->setCustomPrice($price);
386:             $item->setBaseCustomPrice($basePrice);
387:         }
388:         $item->setPrice($basePrice);
389:         $item->setBasePrice($basePrice);
390:         $item->setRowTotal($subtotal);
391:         $item->setBaseRowTotal($baseSubtotal);
392:         $item->setPriceInclTax($taxPrice);
393:         $item->setBasePriceInclTax($baseTaxPrice);
394:         $item->setRowTotalInclTax($taxSubtotal);
395:         $item->setBaseRowTotalInclTax($baseTaxSubtotal);
396:         $item->setTaxableAmount($taxable);
397:         $item->setBaseTaxableAmount($baseTaxable);
398:         $item->setIsPriceInclTax($isPriceInclTax);
399:         if ($this->_config->discountTax($this->_store)) {
400:             $item->setDiscountCalculationPrice($taxSubtotal/$qty);
401:             $item->setBaseDiscountCalculationPrice($baseTaxSubtotal/$qty);
402:         } elseif ($isPriceInclTax) {
403:             $item->setDiscountCalculationPrice($subtotal/$qty);
404:             $item->setBaseDiscountCalculationPrice($baseSubtotal/$qty);
405:         }
406: 
407:         return $this;
408:     }
409: 
410:     /**
411:      * Calculate item price and row total including/excluding tax based on total price rounding level
412:      *
413:      * @param Mage_Sales_Model_Quote_Item_Abstract $item
414:      * @param Varien_Object $request
415:      * @return Mage_Tax_Model_Sales_Total_Quote_Subtotal
416:      */
417:     protected function _totalBaseCalculation($item, $request)
418:     {
419:         $calc   = $this->_calculator;
420:         $request->setProductClassId($item->getProduct()->getTaxClassId());
421:         $rate   = $calc->getRate($request);
422:         $qty    = $item->getTotalQty();
423: 
424:         $price          = $taxPrice         = $item->getCalculationPriceOriginal();
425:         $basePrice      = $baseTaxPrice     = $item->getBaseCalculationPriceOriginal();
426:         $subtotal       = $taxSubtotal      = $item->getRowTotal();
427:         $baseSubtotal   = $baseTaxSubtotal  = $item->getBaseRowTotal();
428: 
429:         $taxOnOrigPrice = !$this->_helper->applyTaxOnCustomPrice($this->_store) && $item->hasCustomPrice();
430:         if ($taxOnOrigPrice) {
431:             $origSubtotal       = $item->getOriginalPrice() * $qty;
432:             $baseOrigSubtotal   = $item->getBaseOriginalPrice() * $qty;
433:         }
434:         $item->setTaxPercent($rate);
435:         if ($this->_config->priceIncludesTax($this->_store)) {
436:             if ($this->_sameRateAsStore($request)) {
437:                 if ($taxOnOrigPrice) {
438:                     $rowTax =
439:                         $this->_deltaRound($calc->calcTaxAmount($origSubtotal, $rate, true, false), $rate, true);
440:                     $baseRowTax =
441:                         $this->_deltaRound(
442:                             $calc->calcTaxAmount($baseOrigSubtotal, $rate, true, false), $rate, true, 'base'
443:                         );
444: 
445:                     $taxable        = $origSubtotal;
446:                     $baseTaxable    = $baseOrigSubtotal;
447:                 } else {
448:                     $rowTax =
449:                         $this->_deltaRound($calc->calcTaxAmount($subtotal, $rate, true, false), $rate, true);
450:                     $baseRowTax =
451:                         $this->_deltaRound(
452:                             $calc->calcTaxAmount($baseSubtotal, $rate, true, false), $rate, true, 'base'
453:                         );
454: 
455:                     $taxable        = $subtotal;
456:                     $baseTaxable    = $baseSubtotal;
457:                 }
458:                 $taxPrice       = $price;
459:                 $baseTaxPrice   = $basePrice;
460: 
461:                 $taxSubtotal    = $subtotal;
462:                 $baseTaxSubtotal= $baseSubtotal;
463: 
464:                 $subtotal       = $subtotal - $rowTax;
465:                 $baseSubtotal   = $baseSubtotal - $baseRowTax;
466: 
467:                 $price          = $calc->round($subtotal/$qty);
468:                 $basePrice      = $calc->round($baseSubtotal/$qty);
469: 
470:                 $isPriceInclTax = true;
471:             } else {
472:                 $storeRate      = $calc->getStoreRate($request, $this->_store);
473:                 if ($taxOnOrigPrice) {
474:                     $storeTax           = $calc->calcTaxAmount($origSubtotal, $storeRate, true, false);
475:                     $baseStoreTax       = $calc->calcTaxAmount($baseOrigSubtotal, $storeRate, true, false);
476:                 } else {
477:                     $storeTax           = $calc->calcTaxAmount($subtotal, $storeRate, true, false);
478:                     $baseStoreTax       = $calc->calcTaxAmount($baseSubtotal, $storeRate, true, false);
479:                 }
480:                 $subtotal       = $calc->round($subtotal - $storeTax);
481:                 $baseSubtotal   = $calc->round($baseSubtotal - $baseStoreTax);
482: 
483:                 $price          = $calc->round($subtotal/$qty);
484:                 $basePrice      = $calc->round($baseSubtotal/$qty);
485: 
486:                 $rowTax =
487:                     $this->_deltaRound($calc->calcTaxAmount($subtotal, $rate, false, false), $rate, true);
488:                 $baseRowTax =
489:                     $this->_deltaRound(
490:                         $calc->calcTaxAmount($baseSubtotal, $rate, false, false), $rate, true, 'base'
491:                     );
492: 
493:                 $taxSubtotal    = $subtotal + $rowTax;
494:                 $baseTaxSubtotal= $baseSubtotal + $baseRowTax;
495: 
496:                 $taxPrice       = $calc->round($taxSubtotal/$qty);
497:                 $baseTaxPrice   = $calc->round($baseTaxSubtotal/$qty);
498: 
499:                 $taxable        = $subtotal;
500:                 $baseTaxable    = $baseSubtotal;
501: 
502:                 $isPriceInclTax = false;
503:             }
504:         } else {
505:             if ($taxOnOrigPrice) {
506:                 $rowTax =
507:                     $this->_deltaRound($calc->calcTaxAmount($origSubtotal, $rate, false, false), $rate, true);
508:                 $baseRowTax =
509:                     $this->_deltaRound(
510:                         $calc->calcTaxAmount($baseOrigSubtotal, $rate, false, false), $rate, true, 'base'
511:                     );
512: 
513:                 $taxable        = $origSubtotal;
514:                 $baseTaxable    = $baseOrigSubtotal;
515:             } else {
516:                 $rowTax         = $this->_deltaRound($calc->calcTaxAmount($subtotal, $rate, false, false), $rate, true);
517:                 $baseRowTax     =
518:                     $this->_deltaRound($calc->calcTaxAmount($baseSubtotal, $rate, false, false), $rate, true, 'base');
519: 
520:                 $taxable        = $subtotal;
521:                 $baseTaxable    = $baseSubtotal;
522:             }
523: 
524:             $taxSubtotal    = $subtotal + $rowTax;
525:             $baseTaxSubtotal= $baseSubtotal + $baseRowTax;
526: 
527:             $taxPrice       = $calc->round($taxSubtotal/$qty);
528:             $baseTaxPrice   = $calc->round($baseTaxSubtotal/$qty);
529: 
530:             $isPriceInclTax = false;
531:         }
532: 
533:         if ($item->hasCustomPrice()) {
534:             /**
535:              * Initialize item original price before declaring custom price
536:              */
537:             $item->getOriginalPrice();
538:             $item->setCustomPrice($price);
539:             $item->setBaseCustomPrice($basePrice);
540:         } else {
541:             $item->setConvertedPrice($price);
542:         }
543:         $item->setPrice($basePrice);
544:         $item->setBasePrice($basePrice);
545:         $item->setRowTotal($subtotal);
546:         $item->setBaseRowTotal($baseSubtotal);
547:         $item->setPriceInclTax($taxPrice);
548:         $item->setBasePriceInclTax($baseTaxPrice);
549:         $item->setRowTotalInclTax($taxSubtotal);
550:         $item->setBaseRowTotalInclTax($baseTaxSubtotal);
551:         $item->setTaxableAmount($taxable);
552:         $item->setBaseTaxableAmount($baseTaxable);
553:         $item->setIsPriceInclTax($isPriceInclTax);
554:         if ($this->_config->discountTax($this->_store)) {
555:             $item->setDiscountCalculationPrice($taxSubtotal/$qty);
556:             $item->setBaseDiscountCalculationPrice($baseTaxSubtotal/$qty);
557:         } elseif ($isPriceInclTax) {
558:             $item->setDiscountCalculationPrice($subtotal/$qty);
559:             $item->setBaseDiscountCalculationPrice($baseSubtotal/$qty);
560:         }
561:         return $this;
562:     }
563: 
564:     /**
565:      * Checks whether request for an item has same rate as store one
566:      * Used only after collect() started, as far as uses optimized $_areTaxRequestsSimilar property
567:      * Used only in case of prices including tax
568:      *
569:      * @param Varien_Object $request
570:      * @return bool
571:      */
572:     protected function _sameRateAsStore($request)
573:     {
574:         // Maybe we know that all requests for currently collected items have same rates
575:         if ($this->_areTaxRequestsSimilar) {
576:             return true;
577:         }
578: 
579:         // Check current request individually
580:         $rate = $this->_calculator->getRate($request);
581:         $storeRate = $this->_calculator->getStoreRate($request, $this->_store);
582:         return $rate == $storeRate;
583:     }
584: 
585:     /**
586:      * Round price based on previous rounding operation delta
587:      *
588:      * @param float $price
589:      * @param string $rate
590:      * @param bool $direction
591:      * @param string $type
592:      * @return float
593:      */
594:     protected function _deltaRound($price, $rate, $direction, $type='regular')
595:     {
596:         if ($price) {
597:             $rate  = (string) $rate;
598:             $type  = $type . $direction;
599:             $delta = isset($this->_roundingDeltas[$type][$rate]) ? $this->_roundingDeltas[$type][$rate] : 0;
600:             $price += $delta;
601:             $this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);
602:             $price = $this->_calculator->round($price);
603:         }
604:         return $price;
605:     }
606: 
607:     /**
608:      * Recalculate row information for item based on children calculation
609:      *
610:      * @param   Mage_Sales_Model_Quote_Item_Abstract $item
611:      * @return  Mage_Tax_Model_Sales_Total_Quote_Subtotal
612:      */
613:     protected function _recalculateParent(Mage_Sales_Model_Quote_Item_Abstract $item)
614:     {
615:         $price       = 0;
616:         $basePrice   = 0;
617:         $rowTotal    = 0;
618:         $baseRowTotal= 0;
619:         $priceInclTax       = 0;
620:         $basePriceInclTax   = 0;
621:         $rowTotalInclTax    = 0;
622:         $baseRowTotalInclTax= 0;
623:         foreach ($item->getChildren() as $child) {
624:             $price              += $child->getPrice() * $child->getQty();
625:             $basePrice          += $child->getBasePrice() * $child->getQty();
626:             $rowTotal           += $child->getRowTotal();
627:             $baseRowTotal       += $child->getBaseRowTotal();
628:             $priceInclTax       += $child->getPriceInclTax() * $child->getQty();
629:             $basePriceInclTax   += $child->getBasePriceInclTax() * $child->getQty();
630:             $rowTotalInclTax    += $child->getRowTotalInclTax();
631:             $baseRowTotalInclTax+= $child->getBaseRowTotalInclTax();
632:         }
633:         $item->setConvertedPrice($price);
634:         $item->setPrice($basePrice);
635:         $item->setRowTotal($rowTotal);
636:         $item->setBaseRowTotal($baseRowTotal);
637:         $item->setPriceInclTax($priceInclTax);
638:         $item->setBasePriceInclTax($basePriceInclTax);
639:         $item->setRowTotalInclTax($rowTotalInclTax);
640:         $item->setBaseRowTotalInclTax($baseRowTotalInclTax);
641:         return $this;
642:     }
643: 
644:     /**
645:      * Get request for fetching store tax rate
646:      *
647:      * @param   Mage_Sales_Model_Quote_Address $address
648:      * @return  Varien_Object
649:      */
650:     protected function _getStoreTaxRequest($address)
651:     {
652:         if (is_null($this->_storeTaxRequest)) {
653:             $this->_storeTaxRequest = $this->_calculator->getRateOriginRequest($address->getQuote()->getStore());
654:         }
655:         return $this->_storeTaxRequest;
656:     }
657: 
658:     /**
659:      * Get request for fetching address tax rate
660:      *
661:      * @param   Mage_Sales_Model_Quote_Address $address
662:      * @return  Varien_Object
663:      */
664:     protected function _getAddressTaxRequest($address)
665:     {
666:         $addressTaxRequest = $this->_calculator->getRateRequest(
667:             $address,
668:             $address->getQuote()->getBillingAddress(),
669:             $address->getQuote()->getCustomerTaxClassId(),
670:             $address->getQuote()->getStore()
671:         );
672:         return $addressTaxRequest;
673:     }
674: 
675:     /**
676:      * Add row total item amount to subtotal
677:      *
678:      * @param   Mage_Sales_Model_Quote_Address $address
679:      * @param   Mage_Sales_Model_Quote_Item_Abstract $item
680:      * @return  Mage_Tax_Model_Sales_Total_Quote_Subtotal
681:      */
682:     protected function _addSubtotalAmount(Mage_Sales_Model_Quote_Address $address, $item)
683:     {
684:         $address->setTotalAmount('subtotal', $address->getTotalAmount('subtotal')+$item->getRowTotal());
685:         $address->setBaseTotalAmount('subtotal', $address->getBaseTotalAmount('subtotal')+$item->getBaseRowTotal());
686:         $address->setSubtotalInclTax($address->getSubtotalInclTax()+$item->getRowTotalInclTax());
687:         $address->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax()+$item->getBaseRowTotalInclTax());
688:         return $this;
689:     }
690: 
691: 
692: 
693: 
694: 
695: 
696: 
697: 
698: 
699: 
700: 
701: 
702: 
703: 
704:     /**
705:      * Unset item prices/totals with price include tax.
706:      * Operation is necessary for reset item state in case if configuration was changed
707:      *
708:      * @deprecated after 1.4.1
709:      * @param   Mage_Sales_Model_Quote_Item_Abstract $item
710:      * @return  Mage_Tax_Model_Sales_Total_Quote_Subtotal
711:      */
712:     protected function _resetItemPriceInclTax(Mage_Sales_Model_Quote_Item_Abstract $item)
713:     {
714:         $item->setPriceInclTax(null);
715:         $item->setBasePriceInclTax(null);
716:         $item->setRowTotalInclTax(null);
717:         $item->setBaseRowTotalInclTax(null);
718:         return $this;
719:     }
720: 
721:     /**
722:      *
723:      * @deprecated after 1.4.0.1
724:      * @param   Mage_Sales_Model_Quote_Address $address
725:      * @return  Mage_Tax_Model_Sales_Total_Quote_Subtotal
726:      */
727:     protected function _processShippingAmount($address)
728:     {
729:         return $this;
730:     }
731: 
732:     /**
733:      * Recollect item price and row total using after taxes subtract.
734:      * Declare item price including tax attributes
735:      * @deprecated after 1.4.1
736:      * @param   Mage_Sales_Model_Quote_Item_Abstract $item
737:      * @return  Mage_Tax_Model_Sales_Total_Quote_Subtotal
738:      */
739:     protected function _recollectItem($address, Mage_Sales_Model_Quote_Item_Abstract $item)
740:     {
741:         $store   = $address->getQuote()->getStore();
742:         $request = $this->_getStoreTaxRequest($address);
743:         $request->setProductClassId($item->getProduct()->getTaxClassId());
744:         $rate   = $this->_calculator->getRate($request);
745:         $qty    = $item->getTotalQty();
746: 
747:         $price          = $taxPrice         = $item->getCalculationPriceOriginal();
748:         $basePrice      = $baseTaxPrice     = $item->getBaseCalculationPriceOriginal();
749:         $subtotal       = $taxSubtotal      = $item->getRowTotal();
750:         $baseSubtotal   = $baseTaxSubtotal  = $item->getBaseRowTotal();
751: 
752:         if ($this->_config->discountTax($store)) {
753:             $item->setDiscountCalculationPrice($price);
754:             $item->setBaseDiscountCalculationPrice($basePrice);
755:         }
756: 
757:         /**
758:          * Use original price for tax calculation
759:          */
760:         if ($item->hasCustomPrice() && !$this->_helper->applyTaxOnCustomPrice($store)) {
761:             $taxPrice         = $item->getOriginalPrice();
762:             $baseTaxPrice     = $item->getBaseOriginalPrice();
763:             $taxSubtotal      = $taxPrice*$qty;
764:             $baseTaxSubtotal  = $baseTaxPrice*$qty;
765:         }
766: 
767:         if ($this->_areTaxRequestsSimilar) {
768:             $item->setRowTotalInclTax($subtotal);
769:             $item->setBaseRowTotalInclTax($baseSubtotal);
770:             $item->setPriceInclTax($price);
771:             $item->setBasePriceInclTax($basePrice);
772: 
773:             $item->setTaxCalcPrice($taxPrice);
774:             $item->setBaseTaxCalcPrice($baseTaxPrice);
775:             $item->setTaxCalcRowTotal($taxSubtotal);
776:             $item->setBaseTaxCalcRowTotal($baseTaxSubtotal);
777:         }
778: 
779:         $this->_subtotalInclTax     += $subtotal;
780:         $this->_baseSubtotalInclTax += $baseSubtotal;
781: 
782:         if ($this->_config->getAlgorithm($store) == Mage_Tax_Model_Calculation::CALC_UNIT_BASE) {
783:             $taxAmount      = $this->_calculator->calcTaxAmount($taxPrice, $rate, true);
784:             $baseTaxAmount  = $this->_calculator->calcTaxAmount($baseTaxPrice, $rate, true);
785:             $unitPrice      = $this->_calculator->round($price-$taxAmount);
786:             $baseUnitPrice  = $this->_calculator->round($basePrice-$baseTaxAmount);
787:             $subtotal       = $this->_calculator->round($unitPrice*$qty);
788:             $baseSubtotal   = $this->_calculator->round($baseUnitPrice*$qty);
789:         } else {
790:             $taxAmount      = $this->_calculator->calcTaxAmount($taxSubtotal, $rate, true, false);
791:             $baseTaxAmount  = $this->_calculator->calcTaxAmount($baseTaxSubtotal, $rate, true, false);
792:             $unitPrice      = ($subtotal-$taxAmount)/$qty;
793:             $baseUnitPrice  = ($baseSubtotal-$baseTaxAmount)/$qty;
794:             $subtotal       = $this->_calculator->round(($subtotal-$taxAmount));
795:             $baseSubtotal   = $this->_calculator->round(($baseSubtotal-$baseTaxAmount));
796:         }
797: 
798:         if ($item->hasCustomPrice()) {
799:             $item->setCustomPrice($unitPrice);
800:             $item->setBaseCustomPrice($baseUnitPrice);
801:         }
802:         $item->setPrice($baseUnitPrice);
803:         $item->setOriginalPrice($unitPrice);
804:         $item->setBasePrice($baseUnitPrice);
805:         $item->setRowTotal($subtotal);
806:         $item->setBaseRowTotal($baseSubtotal);
807:         return $this;
808:     }
809: 
810:     /**
811:      * Check if we need subtract store tax amount from item prices
812:      *
813:      * @deprecated after 1.4.1
814:      * @param Mage_Sales_Model_Quote_Address $address
815:      * @return bool
816:      */
817:     protected function _needSubtractTax($address)
818:     {
819:         $store = $address->getQuote()->getStore();
820:         if ($this->_config->priceIncludesTax($store) || $this->_config->getNeedUsePriceExcludeTax()) {
821:             return true;
822:         }
823:         return false;
824:     }
825: 
826:     /**
827:      * @deprecated after 1.4.0.1
828:      *
829:      * @param Mage_Sales_Model_Quote_Address $address
830:      * @return bool
831:      */
832:     protected function _needSubtractShippingTax($address)
833:     {
834:         $store = $address->getQuote()->getStore();
835:         if ($this->_config->shippingPriceIncludesTax($store) || $this->_config->getNeedUseShippingExcludeTax()) {
836:             return true;
837:         }
838:         return false;
839:     }
840: }
841: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0