Magento supports tier prices feature and it allows the actual price to be determined by the quantities. This is a common sale promotion technique used by lots of Magento store owners.
Mageno product model Mage_Catalog_Model_Product has two methods which are related to tire prices:
/**
* Get product tier price by qty
*
* @param double $qty
* @return double
*/
public function getTierPrice($qty=null)
{
return $this->getPriceModel()->getTierPrice($qty, $this);
}
/**
* Count how many tier prices we have for the product
*
* @return int
*/
public function getTierPriceCount()
{
return $this->getPriceModel()->getTierPriceCount($this);
}
From above-mentioned methods, we know that product's tire prices is determined by price model. Magento uses price factory design pattern to cover all kinds of product types: simple, configurable,group, virtual, downloadable.
public function getPriceModel()
{
return Mage::getSingleton('catalog/product_type')->priceFactory($this->getTypeId());
}
class Mage_Catalog_Model_Product_Type is a helper or utility class which can get all the product types information from configuration file and database.
public static function priceFactory($productType)
{
if (isset(self::$_priceModels[$productType])) {
return self::$_priceModels[$productType];
}
$types = self::getTypes();
if (!empty($types[$productType]['price_model'])) {
$priceModelName = $types[$productType]['price_model'];
} else {
$priceModelName = self::DEFAULT_PRICE_MODEL;
}
self::$_priceModels[$productType] = Mage::getModel($priceModelName);
return self::$_priceModels[$productType];
}
<product>
<type>
<simple translate="label" module="catalog">
<label>Simple Product</label>
<model>catalog/product_type_simple</model>
<composite>0</composite>
<index_priority>10</index_priority>
</simple>
<grouped translate="label" module="catalog">
<label>Grouped Product</label>
<model>catalog/product_type_grouped</model>
<price_model>catalog/product_type_grouped_price</price_model>
<composite>1</composite>
<allow_product_types>
<simple/>
<virtual/>
</allow_product_types>
<index_priority>50</index_priority>
<price_indexer>catalog/product_indexer_price_grouped</price_indexer>
</grouped>
<configurable translate="label" module="catalog">
<label>Configurable Product</label>
<model>catalog/product_type_configurable</model>
<price_model>catalog/product_type_configurable_price</price_model>
<composite>1</composite>
<allow_product_types>
<simple/>
<virtual/>
</allow_product_types>
<index_priority>30</index_priority>
<price_indexer>catalog/product_indexer_price_configurable</price_indexer>
</configurable>
<virtual translate="label" module="catalog">
<label>Virtual Product</label>
<model>catalog/product_type_virtual</model>
<composite>0</composite>
<index_priority>20</index_priority>
</virtual>
</type>
</product>
For simplicity, i prefer to use simple type product's price model to show you around. class Mage_Catalog_Model_Product_Type_Price is the simple type product's default price model.
public function getTierPrice($qty = null, $product)
{
$allGroups = Mage_Customer_Model_Group::CUST_GROUP_ALL;
$prices = $product->getData('tier_price');
$custGroup = $this->_getCustomerGroupId($product);
if ($qty) {
$prevQty = 1;
$prevPrice = $product->getPrice();
$prevGroup = $allGroups;
foreach ($prices as $price) {
if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) {
continue;
}
if ($qty < $price['price_qty']) {
continue;
}
if ($price['price_qty'] < $prevQty) {
continue;
}
if ($price['price_qty'] == $prevQty && $prevGroup != $allGroups && $price['cust_group'] == $allGroups) {
// found tier qty is same as current tier qty but current tier group is ALL_GROUPS
continue;
}
if ($price['website_price'] < $prevPrice) {
$prevPrice = $price['website_price'];
$prevQty = $price['price_qty'];
$prevGroup = $price['cust_group'];
}
}
return $prevPrice;
}
return ($prices) ? $prices : array();
}
The logic is very apparently because it fetches the tire prices set up by admin panel and compares the quantity to get the corresponding price.