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_Bundle_Adminhtml_Bundle_Product_EditController
  • Mage_Bundle_Adminhtml_Bundle_SelectionController
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Checkbox
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Multi
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Radio
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Select
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Attributes
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Attributes_Extend
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Attributes_Special
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Search
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Search_Grid
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Selection
  • Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tabs
  • Mage_Bundle_Block_Adminhtml_Sales_Order_Items_Renderer
  • Mage_Bundle_Block_Adminhtml_Sales_Order_View_Items_Renderer
  • Mage_Bundle_Block_Catalog_Product_List_Partof
  • Mage_Bundle_Block_Catalog_Product_Price
  • Mage_Bundle_Block_Catalog_Product_View
  • Mage_Bundle_Block_Catalog_Product_View_Type_Bundle
  • Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option
  • Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox
  • Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Multi
  • Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Radio
  • Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Select
  • Mage_Bundle_Block_Checkout_Cart_Item_Renderer
  • Mage_Bundle_Block_Sales_Order_Items_Renderer
  • Mage_Bundle_Helper_Catalog_Product_Configuration
  • Mage_Bundle_Helper_Data
  • Mage_Bundle_Model_CatalogIndex_Data_Bundle
  • Mage_Bundle_Model_Mysql4_Bundle
  • Mage_Bundle_Model_Mysql4_Indexer_Price
  • Mage_Bundle_Model_Mysql4_Indexer_Stock
  • Mage_Bundle_Model_Mysql4_Option
  • Mage_Bundle_Model_Mysql4_Option_Collection
  • Mage_Bundle_Model_Mysql4_Price_Index
  • Mage_Bundle_Model_Mysql4_Selection
  • Mage_Bundle_Model_Mysql4_Selection_Collection
  • Mage_Bundle_Model_Observer
  • Mage_Bundle_Model_Option
  • Mage_Bundle_Model_Price_Index
  • Mage_Bundle_Model_Product_Attribute_Source_Price_View
  • Mage_Bundle_Model_Product_Price
  • Mage_Bundle_Model_Product_Type
  • Mage_Bundle_Model_Resource_Bundle
  • Mage_Bundle_Model_Resource_Indexer_Price
  • Mage_Bundle_Model_Resource_Indexer_Stock
  • Mage_Bundle_Model_Resource_Option
  • Mage_Bundle_Model_Resource_Option_Collection
  • Mage_Bundle_Model_Resource_Price_Index
  • Mage_Bundle_Model_Resource_Selection
  • Mage_Bundle_Model_Resource_Selection_Collection
  • Mage_Bundle_Model_Sales_Order_Pdf_Items_Abstract
  • Mage_Bundle_Model_Sales_Order_Pdf_Items_Shipment
  • Mage_Bundle_Model_Selection
  • Mage_Bundle_Model_Source_Option_Selection_Price_Type
  • Mage_Bundle_Model_Source_Option_Type
  • 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_Bundle
 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:  * Bundle Price Model
 29:  *
 30:  * @category Mage
 31:  * @package  Mage_Bundle
 32:  * @author   Magento Core Team <core@magentocommerce.com>
 33:  */
 34: class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Price
 35: {
 36:     const PRICE_TYPE_FIXED      = 1;
 37:     const PRICE_TYPE_DYNAMIC    = 0;
 38: 
 39:     /**
 40:      * Flag which indicates - is min/max prices have been calculated by index
 41:      *
 42:      * @var bool
 43:      */
 44:     protected $_isPricesCalculatedByIndex;
 45: 
 46:     /**
 47:      * Is min/max prices have been calculated by index
 48:      *
 49:      * @return bool
 50:      */
 51:     public function getIsPricesCalculatedByIndex()
 52:     {
 53:         return $this->_isPricesCalculatedByIndex;
 54:     }
 55: 
 56:     /**
 57:      * Return product base price
 58:      *
 59:      * @param Mage_Catalog_Model_Product $product
 60:      * @return string
 61:      */
 62:     public function getPrice($product)
 63:     {
 64:         if ($product->getPriceType() == self::PRICE_TYPE_FIXED) {
 65:             return $product->getData('price');
 66:         } else {
 67:             return 0;
 68:         }
 69:     }
 70: 
 71:     /**
 72:      * Get Total price  for Bundle items
 73:      *
 74:      * @param Mage_Catalog_Model_Product $product
 75:      * @param null|float $qty
 76:      * @return float
 77:      */
 78:     public function getTotalBundleItemsPrice($product, $qty = null)
 79:     {
 80:         $price = 0.0;
 81:         if ($product->hasCustomOptions()) {
 82:             $customOption = $product->getCustomOption('bundle_selection_ids');
 83:             if ($customOption) {
 84:                 $selectionIds = unserialize($customOption->getValue());
 85:                 $selections = $product->getTypeInstance(true)->getSelectionsByIds($selectionIds, $product);
 86:                 $selections->addTierPriceData();
 87:                 Mage::dispatchEvent('prepare_catalog_product_collection_prices', array(
 88:                     'collection' => $selections,
 89:                     'store_id' => $product->getStoreId(),
 90:                 ));
 91:                 foreach ($selections->getItems() as $selection) {
 92:                     if ($selection->isSalable()) {
 93:                         $selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId());
 94:                         if ($selectionQty) {
 95:                             $price += $this->getSelectionFinalTotalPrice($product, $selection, $qty,
 96:                                 $selectionQty->getValue());
 97:                         }
 98:                     }
 99:                 }
100:             }
101:         }
102:         return $price;
103:     }
104: 
105:     /**
106:      * Get product final price
107:      *
108:      * @param   double                     $qty
109:      * @param   Mage_Catalog_Model_Product $product
110:      * @return  double
111:      */
112:     public function getFinalPrice($qty = null, $product)
113:     {
114:         if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) {
115:             return $product->getCalculatedFinalPrice();
116:         }
117: 
118:         $finalPrice = $this->getBasePrice($product, $qty);
119:         $product->setFinalPrice($finalPrice);
120:         Mage::dispatchEvent('catalog_product_get_final_price', array('product' => $product, 'qty' => $qty));
121:         $finalPrice = $product->getData('final_price');
122: 
123:         $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice);
124:         $finalPrice += $this->getTotalBundleItemsPrice($product, $qty);
125: 
126:         $product->setFinalPrice($finalPrice);
127:         return max(0, $product->getData('final_price'));
128:     }
129: 
130:     /**
131:      * Returns final price of a child product
132:      *
133:      * @param Mage_Catalog_Model_Product $product
134:      * @param float                      $productQty
135:      * @param Mage_Catalog_Model_Product $childProduct
136:      * @param float                      $childProductQty
137:      * @return decimal
138:      */
139:     public function getChildFinalPrice($product, $productQty, $childProduct, $childProductQty)
140:     {
141:         return $this->getSelectionFinalTotalPrice($product, $childProduct, $productQty, $childProductQty, false);
142:     }
143: 
144:     /**
145:      * Retrieve Price
146:      *
147:      * @deprecated after 1.5.1.0
148:      * @see Mage_Bundle_Model_Product_Price::getTotalPrices()
149:      *
150:      * @param  Mage_Catalog_Model_Product $product
151:      * @param  string                     $which
152:      * @return decimal|array
153:      */
154:     public function getPrices($product, $which = null)
155:     {
156:         return $this->getTotalPrices($product, $which);
157:     }
158: 
159:     /**
160:      * Retrieve Prices depending on tax
161:      *
162:      * @deprecated after 1.5.1.0
163:      * @see Mage_Bundle_Model_Product_Price::getTotalPrices()
164:      *
165:      * @param  Mage_Catalog_Model_Product $product
166:      * @param  string                     $which
167:      * @param  bool|null                  $includeTax
168:      * @return decimal|array
169:      */
170:     public function getPricesDependingOnTax($product, $which = null, $includeTax = null)
171:     {
172:         return $this->getTotalPrices($product, $which, $includeTax);
173:     }
174: 
175:     /**
176:      * Retrieve Price considering tier price
177:      *
178:      * @param  Mage_Catalog_Model_Product $product
179:      * @param  string|null                $which
180:      * @param  bool|null                  $includeTax
181:      * @param  bool                       $takeTierPrice
182:      * @return decimal|array
183:      */
184:     public function getTotalPrices($product, $which = null, $includeTax = null, $takeTierPrice = true)
185:     {
186:         // check calculated price index
187:         if ($product->getData('min_price') && $product->getData('max_price')) {
188:             $minimalPrice = Mage::helper('tax')->getPrice($product, $product->getData('min_price'), $includeTax);
189:             $maximalPrice = Mage::helper('tax')->getPrice($product, $product->getData('max_price'), $includeTax);
190:             $this->_isPricesCalculatedByIndex = true;
191:         } else {
192:             /**
193:              * Check if product price is fixed
194:              */
195:             $finalPrice = $product->getFinalPrice();
196:             if ($product->getPriceType() == self::PRICE_TYPE_FIXED) {
197:                 $minimalPrice = $maximalPrice = Mage::helper('tax')->getPrice($product, $finalPrice, $includeTax);
198:             } else { // PRICE_TYPE_DYNAMIC
199:                 $minimalPrice = $maximalPrice = 0;
200:             }
201: 
202:             $options = $this->getOptions($product);
203:             $minPriceFounded = false;
204: 
205:             if ($options) {
206:                 foreach ($options as $option) {
207:                     /* @var $option Mage_Bundle_Model_Option */
208:                     $selections = $option->getSelections();
209:                     if ($selections) {
210:                         $selectionMinimalPrices = array();
211:                         $selectionMaximalPrices = array();
212: 
213:                         foreach ($option->getSelections() as $selection) {
214:                             /* @var $selection Mage_Bundle_Model_Selection */
215:                             if (!$selection->isSalable()) {
216:                                 /**
217:                                  * @todo CatalogInventory Show out of stock Products
218:                                  */
219:                                 continue;
220:                             }
221: 
222:                             $qty = $selection->getSelectionQty();
223: 
224:                             $item = $product->getPriceType() == self::PRICE_TYPE_FIXED ? $product : $selection;
225: 
226:                             $selectionMinimalPrices[] = Mage::helper('tax')->getPrice(
227:                                 $item,
228:                                 $this->getSelectionFinalTotalPrice($product, $selection, 1, $qty, true, $takeTierPrice),
229:                                 $includeTax
230:                             );
231:                             $selectionMaximalPrices[] = Mage::helper('tax')->getPrice(
232:                                 $item,
233:                                 $this->getSelectionFinalTotalPrice($product, $selection, 1, null, true, $takeTierPrice),
234:                                 $includeTax
235:                             );
236:                         }
237: 
238:                         if (count($selectionMinimalPrices)) {
239:                             $selMinPrice = min($selectionMinimalPrices);
240:                             if ($option->getRequired()) {
241:                                 $minimalPrice += $selMinPrice;
242:                                 $minPriceFounded = true;
243:                             } elseif (true !== $minPriceFounded) {
244:                                 $selMinPrice += $minimalPrice;
245:                                 $minPriceFounded = (false === $minPriceFounded)
246:                                     ? $selMinPrice
247:                                     : min($minPriceFounded, $selMinPrice);
248:                             }
249: 
250:                             if ($option->isMultiSelection()) {
251:                                 $maximalPrice += array_sum($selectionMaximalPrices);
252:                             } else {
253:                                 $maximalPrice += max($selectionMaximalPrices);
254:                             }
255:                         }
256:                     }
257:                 }
258:             }
259:             // condition is TRUE when all product options are NOT required
260:             if (!is_bool($minPriceFounded)) {
261:                 $minimalPrice = $minPriceFounded;
262:             }
263: 
264:             $customOptions = $product->getOptions();
265:             if ($product->getPriceType() == self::PRICE_TYPE_FIXED && $customOptions) {
266:                 foreach ($customOptions as $customOption) {
267:                     /* @var $customOption Mage_Catalog_Model_Product_Option */
268:                     $values = $customOption->getValues();
269:                     if ($values) {
270:                         $prices = array();
271:                         foreach ($values as $value) {
272:                             /* @var $value Mage_Catalog_Model_Product_Option_Value */
273:                             $valuePrice = $value->getPrice(true);
274: 
275:                             $prices[] = $valuePrice;
276:                         }
277:                         if (count($prices)) {
278:                             if ($customOption->getIsRequire()) {
279:                                 $minimalPrice += Mage::helper('tax')->getPrice($product, min($prices), $includeTax);
280:                             }
281: 
282:                             $multiTypes = array(
283:                                 //Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN,
284:                                 Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX,
285:                                 Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE
286:                             );
287: 
288:                             if (in_array($customOption->getType(), $multiTypes)) {
289:                                 $maximalValue = array_sum($prices);
290:                             } else {
291:                                 $maximalValue = max($prices);
292:                             }
293:                             $maximalPrice += Mage::helper('tax')->getPrice($product, $maximalValue, $includeTax);
294:                         }
295:                     } else {
296:                         $valuePrice = $customOption->getPrice(true);
297: 
298:                         if ($customOption->getIsRequire()) {
299:                             $minimalPrice += Mage::helper('tax')->getPrice($product, $valuePrice, $includeTax);
300:                         }
301:                         $maximalPrice += Mage::helper('tax')->getPrice($product, $valuePrice, $includeTax);
302:                     }
303:                 }
304:             }
305:             $this->_isPricesCalculatedByIndex = false;
306:         }
307: 
308:         if ($which == 'max') {
309:             return $maximalPrice;
310:         } elseif ($which == 'min') {
311:             return $minimalPrice;
312:         }
313: 
314:         return array($minimalPrice, $maximalPrice);
315:     }
316: 
317:     /**
318:      * Calculate Minimal price of bundle (counting all required options)
319:      *
320:      * @param  Mage_Catalog_Model_Product $product
321:      * @return decimal
322:      */
323:     public function getMinimalPrice($product)
324:     {
325:         return $this->getPricesTierPrice($product, 'min');
326:     }
327: 
328:     /**
329:      * Calculate maximal price of bundle
330:      *
331:      * @param Mage_Catalog_Model_Product $product
332:      * @return decimal
333:      */
334:     public function getMaximalPrice($product)
335:     {
336:         return $this->getPricesTierPrice($product, 'max');
337:     }
338: 
339:     /**
340:      * Get Options with attached Selections collection
341:      *
342:      * @param Mage_Catalog_Model_Product $product
343:      * @return Mage_Bundle_Model_Mysql4_Option_Collection
344:      */
345:     public function getOptions($product)
346:     {
347:         $product->getTypeInstance(true)
348:             ->setStoreFilter($product->getStoreId(), $product);
349: 
350:         $optionCollection = $product->getTypeInstance(true)
351:             ->getOptionsCollection($product);
352: 
353:         $selectionCollection = $product->getTypeInstance(true)
354:             ->getSelectionsCollection(
355:                 $product->getTypeInstance(true)->getOptionsIds($product),
356:                 $product
357:             );
358: 
359:         return $optionCollection->appendSelections($selectionCollection, false, false);
360:     }
361: 
362:     /**
363:      * Calculate price of selection
364:      *
365:      * @deprecated after 1.6.2.0
366:      * @see Mage_Bundle_Model_Product_Price::getSelectionFinalTotalPrice()
367:      *
368:      * @param Mage_Catalog_Model_Product $bundleProduct
369:      * @param Mage_Catalog_Model_Product $selectionProduct
370:      * @param float|null                 $selectionQty
371:      * @param null|bool                  $multiplyQty      Whether to multiply selection's price by its quantity
372:      * @return float
373:      */
374:     public function getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty = null, $multiplyQty = true)
375:     {
376:         return $this->getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, 0, $selectionQty, $multiplyQty);
377:     }
378: 
379:     /**
380:      * Calculate selection price for front view (with applied special of bundle)
381:      *
382:      * @param Mage_Catalog_Model_Product $bundleProduct
383:      * @param Mage_Catalog_Model_Product $selectionProduct
384:      * @param decimal                    $qty
385:      * @return decimal
386:      */
387:     public function getSelectionPreFinalPrice($bundleProduct, $selectionProduct, $qty = null)
388:     {
389:         return $this->getSelectionPrice($bundleProduct, $selectionProduct, $qty);
390:     }
391: 
392:     /**
393:      * Calculate final price of selection
394:      *
395:      * @deprecated after 1.5.1.0
396:      * @see Mage_Bundle_Model_Product_Price::getSelectionFinalTotalPrice()
397:      *
398:      * @param  Mage_Catalog_Model_Product $bundleProduct
399:      * @param  Mage_Catalog_Model_Product $selectionProduct
400:      * @param  decimal                    $bundleQty
401:      * @param  decimal                    $selectionQty
402:      * @param  bool                       $multiplyQty
403:      * @return decimal
404:      */
405:     public function getSelectionFinalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty = null,
406:        $multiplyQty = true)
407:     {
408:         return $this->getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
409:             $multiplyQty);
410:     }
411: 
412:     /**
413:      * Calculate final price of selection
414:      * with take into account tier price
415:      *
416:      * @param  Mage_Catalog_Model_Product $bundleProduct
417:      * @param  Mage_Catalog_Model_Product $selectionProduct
418:      * @param  decimal                    $bundleQty
419:      * @param  decimal                    $selectionQty
420:      * @param  bool                       $multiplyQty
421:      * @param  bool                       $takeTierPrice
422:      * @return decimal
423:      */
424:     public function getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
425:         $multiplyQty = true, $takeTierPrice = true)
426:     {
427:         if (is_null($selectionQty)) {
428:             $selectionQty = $selectionProduct->getSelectionQty();
429:         }
430: 
431:         if ($bundleProduct->getPriceType() == self::PRICE_TYPE_DYNAMIC) {
432:             $price = $selectionProduct->getFinalPrice($takeTierPrice ? $selectionQty : 1);
433:         } else {
434:             if ($selectionProduct->getSelectionPriceType()) { // percent
435:                 $product = clone $bundleProduct;
436:                 $product->setFinalPrice($this->getPrice($product));
437:                 Mage::dispatchEvent(
438:                     'catalog_product_get_final_price',
439:                     array('product' => $product, 'qty' => $bundleQty)
440:                 );
441:                 $price = $product->getData('final_price') * ($selectionProduct->getSelectionPriceValue() / 100);
442: 
443:             } else { // fixed
444:                 $price = $selectionProduct->getSelectionPriceValue();
445:             }
446:         }
447: 
448:         if ($multiplyQty) {
449:             $price *= $selectionQty;
450:         }
451: 
452:         return min($price,
453:             $this->_applyGroupPrice($bundleProduct, $price),
454:             $this->_applyTierPrice($bundleProduct, $bundleQty, $price),
455:             $this->_applySpecialPrice($bundleProduct, $price)
456:         );
457:     }
458: 
459:     /**
460:      * Apply group price for bundle product
461:      *
462:      * @param Mage_Catalog_Model_Product $product
463:      * @param float $finalPrice
464:      * @return float
465:      */
466:     protected function _applyGroupPrice($product, $finalPrice)
467:     {
468:         $result = $finalPrice;
469:         $groupPrice = $product->getGroupPrice();
470: 
471:         if (is_numeric($groupPrice)) {
472:             $groupPrice = $finalPrice - ($finalPrice * ($groupPrice / 100));
473:             $result = min($finalPrice, $groupPrice);
474:         }
475: 
476:         return $result;
477:     }
478: 
479:     /**
480:      * Get product group price
481:      *
482:      * @param Mage_Catalog_Model_Product $product
483:      * @return float|null
484:      */
485:     public function getGroupPrice($product)
486:     {
487:         $groupPrices = $product->getData('group_price');
488: 
489:         if (is_null($groupPrices)) {
490:             $attribute = $product->getResource()->getAttribute('group_price');
491:             if ($attribute) {
492:                 $attribute->getBackend()->afterLoad($product);
493:                 $groupPrices = $product->getData('group_price');
494:             }
495:         }
496: 
497:         if (is_null($groupPrices) || !is_array($groupPrices)) {
498:             return null;
499:         }
500: 
501:         $customerGroup = $this->_getCustomerGroupId($product);
502: 
503:         $matchedPrice = 0;
504: 
505:         foreach ($groupPrices as $groupPrice) {
506:             if ($groupPrice['cust_group'] == $customerGroup && $groupPrice['website_price'] > $matchedPrice) {
507:                 $matchedPrice = $groupPrice['website_price'];
508:                 break;
509:             }
510:         }
511: 
512:         return $matchedPrice;
513:     }
514: 
515:     /**
516:      * Apply tier price for bundle
517:      *
518:      * @param   Mage_Catalog_Model_Product $product
519:      * @param   decimal                    $qty
520:      * @param   decimal                    $finalPrice
521:      * @return  decimal
522:      */
523:     protected function _applyTierPrice($product, $qty, $finalPrice)
524:     {
525:         if (is_null($qty)) {
526:             return $finalPrice;
527:         }
528: 
529:         $tierPrice  = $product->getTierPrice($qty);
530: 
531:         if (is_numeric($tierPrice)) {
532:             $tierPrice = $finalPrice - ($finalPrice * ($tierPrice / 100));
533:             $finalPrice = min($finalPrice, $tierPrice);
534:         }
535: 
536:         return $finalPrice;
537:     }
538: 
539:     /**
540:      * Get product tier price by qty
541:      *
542:      * @param   decimal                    $qty
543:      * @param   Mage_Catalog_Model_Product $product
544:      * @return  decimal
545:      */
546:     public function getTierPrice($qty=null, $product)
547:     {
548:         $allGroups = Mage_Customer_Model_Group::CUST_GROUP_ALL;
549:         $prices = $product->getData('tier_price');
550: 
551:         if (is_null($prices)) {
552:             if ($attribute = $product->getResource()->getAttribute('tier_price')) {
553:                 $attribute->getBackend()->afterLoad($product);
554:                 $prices = $product->getData('tier_price');
555:             }
556:         }
557: 
558:         if (is_null($prices) || !is_array($prices)) {
559:             if (!is_null($qty)) {
560:                 return $product->getPrice();
561:             }
562:             return array(array(
563:                 'price'         => $product->getPrice(),
564:                 'website_price' => $product->getPrice(),
565:                 'price_qty'     => 1,
566:                 'cust_group'    => $allGroups
567:             ));
568:         }
569: 
570:         $custGroup = $this->_getCustomerGroupId($product);
571:         if ($qty) {
572:             $prevQty = 1;
573:             $prevPrice = 0;
574:             $prevGroup = $allGroups;
575: 
576:             foreach ($prices as $price) {
577:                 if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) {
578:                     // tier not for current customer group nor is for all groups
579:                     continue;
580:                 }
581:                 if ($qty < $price['price_qty']) {
582:                     // tier is higher than product qty
583:                     continue;
584:                 }
585:                 if ($price['price_qty'] < $prevQty) {
586:                     // higher tier qty already found
587:                     continue;
588:                 }
589:                 if ($price['price_qty'] == $prevQty && $prevGroup != $allGroups && $price['cust_group'] == $allGroups) {
590:                     // found tier qty is same as current tier qty but current tier group is ALL_GROUPS
591:                     continue;
592:                 }
593: 
594:                 if ($price['website_price'] > $prevPrice) {
595:                     $prevPrice  = $price['website_price'];
596:                     $prevQty    = $price['price_qty'];
597:                     $prevGroup  = $price['cust_group'];
598:                 }
599:             }
600: 
601:             return $prevPrice;
602:         } else {
603:             $qtyCache = array();
604:             foreach ($prices as $i => $price) {
605:                 if ($price['cust_group'] != $custGroup && $price['cust_group'] != $allGroups) {
606:                     unset($prices[$i]);
607:                 } else if (isset($qtyCache[$price['price_qty']])) {
608:                     $j = $qtyCache[$price['price_qty']];
609:                     if ($prices[$j]['website_price'] < $price['website_price']) {
610:                         unset($prices[$j]);
611:                         $qtyCache[$price['price_qty']] = $i;
612:                     } else {
613:                         unset($prices[$i]);
614:                     }
615:                 } else {
616:                     $qtyCache[$price['price_qty']] = $i;
617:                 }
618:             }
619:         }
620: 
621:         return ($prices) ? $prices : array();
622:     }
623: 
624:     /**
625:      * Calculate product price based on special price data and price rules
626:      *
627:      * @param   float            $basePrice
628:      * @param   float            $specialPrice
629:      * @param   string           $specialPriceFrom
630:      * @param   string           $specialPriceTo
631:      * @param   float|null|false $rulePrice
632:      * @param   mixed            $wId
633:      * @param   mixed            $gId
634:      * @param   null|int         $productId
635:      * @return  float
636:      */
637:     public static function calculatePrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
638:         $rulePrice = false, $wId = null, $gId = null, $productId = null)
639:     {
640:         $resource = Mage::getResourceSingleton('bundle/bundle');
641:         $selectionResource = Mage::getResourceSingleton('bundle/selection');
642:         $productPriceTypeId = Mage::getSingleton('eav/entity_attribute')->getIdByCode(
643:             Mage_Catalog_Model_Product::ENTITY,
644:             'price_type'
645:         );
646: 
647:         if ($wId instanceof Mage_Core_Model_Store) {
648:             $store = $wId->getId();
649:             $wId = $wId->getWebsiteId();
650:         } else {
651:             $store = Mage::app()->getStore($wId)->getId();
652:             $wId = Mage::app()->getStore($wId)->getWebsiteId();
653:         }
654: 
655:         if (!$gId) {
656:             $gId = Mage::getSingleton('customer/session')->getCustomerGroupId();
657:         } else if ($gId instanceof Mage_Customer_Model_Group) {
658:             $gId = $gId->getId();
659:         }
660: 
661:         if (!isset(self::$attributeCache[$productId]['price_type'])) {
662:             $attributes = $resource->getAttributeData($productId, $productPriceTypeId, $store);
663:             self::$attributeCache[$productId]['price_type'] = $attributes;
664:         } else {
665:             $attributes = self::$attributeCache[$productId]['price_type'];
666:         }
667: 
668:         $options = array(0);
669:         $results = $resource->getSelectionsData($productId);
670: 
671:         if (!$attributes || !$attributes[0]['value']) { //dynamic
672:             foreach ($results as $result) {
673:                 if (!$result['product_id']) {
674:                     continue;
675:                 }
676: 
677:                 if ($result['selection_can_change_qty'] && $result['type'] != 'multi'
678:                     && $result['type'] != 'checkbox'
679:                 ) {
680:                     $qty = 1;
681:                 } else {
682:                     $qty = $result['selection_qty'];
683:                 }
684: 
685:                 $result['final_price'] = $selectionResource->getPriceFromIndex($result['product_id'], $qty, $store,
686:                     $gId);
687: 
688:                 $selectionPrice = $result['final_price']*$qty;
689: 
690:                 if (isset($options[$result['option_id']])) {
691:                     $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice);
692:                 } else {
693:                     $options[$result['option_id']] = $selectionPrice;
694:                 }
695:             }
696:             $basePrice = array_sum($options);
697:         } else {
698:             foreach ($results as $result) {
699:                 if (!$result['product_id']) {
700:                     continue;
701:                 }
702:                 if ($result['selection_price_type']) {
703:                     $selectionPrice = $basePrice*$result['selection_price_value']/100;
704:                 } else {
705:                     $selectionPrice = $result['selection_price_value'];
706:                 }
707: 
708:                 if ($result['selection_can_change_qty'] && $result['type'] != 'multi'
709:                     && $result['type'] != 'checkbox'
710:                 ) {
711:                     $qty = 1;
712:                 } else {
713:                     $qty = $result['selection_qty'];
714:                 }
715: 
716:                 $selectionPrice = $selectionPrice*$qty;
717: 
718:                 if (isset($options[$result['option_id']])) {
719:                     $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice);
720:                 } else {
721:                     $options[$result['option_id']] = $selectionPrice;
722:                 }
723:             }
724: 
725:             $basePrice = $basePrice + array_sum($options);
726:         }
727: 
728:         $finalPrice = self::calculateSpecialPrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
729:             $store);
730: 
731:         /**
732:          * adding customer defined options price
733:          */
734:         $customOptions = Mage::getResourceSingleton('catalog/product_option_collection')->reset();
735:         $customOptions->addFieldToFilter('is_require', '1')
736:             ->addProductToFilter($productId)
737:             ->addPriceToResult($store, 'price')
738:             ->addValuesToResult();
739: 
740:         foreach ($customOptions as $customOption) {
741:             if ($values = $customOption->getValues()) {
742:                 $prices = array();
743:                 foreach ($values as $value) {
744:                     $prices[] = $value->getPrice();
745:                 }
746:                 if (count($prices)) {
747:                     $finalPrice += min($prices);
748:                 }
749:             } else {
750:                 $finalPrice += $customOption->getPrice();
751:             }
752:         }
753: 
754:         if ($rulePrice === false) {
755:             $rulePrice = Mage::getResourceModel('catalogrule/rule')
756:                 ->getRulePrice(Mage::app()->getLocale()->storeTimeStamp($store), $wId, $gId, $productId);
757:         }
758: 
759:         if ($rulePrice !== null && $rulePrice !== false) {
760:             $finalPrice = min($finalPrice, $rulePrice);
761:         }
762: 
763:         $finalPrice = max($finalPrice, 0);
764: 
765:         return $finalPrice;
766:     }
767: 
768:     /**
769:      * Calculate and apply special price
770:      *
771:      * @param float  $finalPrice
772:      * @param float  $specialPrice
773:      * @param string $specialPriceFrom
774:      * @param string $specialPriceTo
775:      * @param mixed  $store
776:      * @return float
777:      */
778:     public static function calculateSpecialPrice($finalPrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
779:          $store = null)
780:     {
781:         if (!is_null($specialPrice) && $specialPrice != false) {
782:             if (Mage::app()->getLocale()->isStoreDateInInterval($store, $specialPriceFrom, $specialPriceTo)) {
783:                 $specialPrice   = Mage::app()->getStore()->roundPrice($finalPrice * $specialPrice / 100);
784:                 $finalPrice     = min($finalPrice, $specialPrice);
785:             }
786:         }
787: 
788:         return $finalPrice;
789:     }
790: 
791:     /**
792:      * Check is group price value fixed or percent of original price
793:      *
794:      * @return bool
795:      */
796:     public function isGroupPriceFixed()
797:     {
798:         return false;
799:     }
800: }
801: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0