This has been bugging me for quite a while. Basically, what we are trying to achieve is in the bestsellers on our front page, to have the products listed in the amount sold. For simple products this works fine, however for configurable products they will be displayed as a quantity ordered of 0.
I somehow need to find a way to get the configurable products, find the simple products attached to them, sum the amount sold of these simple products, add this back to the configurable products ID and feed this information back in so it will list the configurable product with the right amount that has been sold.
I have placed, what I believe, the areas of code that require changing. If anyone could help it would be very much appreciated!
Collection.php
class Luxe_Bestsellers_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection
{
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})")
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
$this->getSelect()
->joinInner(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('e.entity_id')
->having('ordered_qty > 0');
return $this;
}
}
List.php
class Luxe_Bestsellers_Block_List extends Mage_Catalog_Block_Product_List
{
protected $_defaultToolbarBlock = 'bestsellers/list_toolbar';
protected function _beforeToHtml() {
$this->addPriceBlockType('bundle', 'bundle/catalog_product_price', 'bundle/catalog/product/price.phtml');
return parent::_beforeToHtml();
}
public function _toHtml()
{
if ($this->_productCollection->count()) {
return parent::_toHtml();
} else {
return '';
}
}
public function getTimeLimit()
{
if ($this->getData('time_limit_in_days')) {
return intval($this->getData('time_limit_in_days'));
} else {
return intval(Mage::getStoreConfig('bestsellers/bestsellers/time_limit_in_days'));
}
}
public function getBlockTitle()
{
if ($this->getData('title')) {
return $this->getData('title');
} else {
return Mage::getStoreConfig('bestsellers/bestsellers/title');
}
}
public function isShowOutOfStock() {
return (bool)Mage::getStoreConfig('bestsellers/bestsellers/show_out_of_stock');
}
public function getProductsLimit()
{
if ($this->getData('limit')) {
return intval($this->getData('limit'));
} else {
return $this->getToolbarBlock()->getLimit();
}
}
public function getDisplayMode()
{
return $this->getData('display_mode');
}
/**
* Retrieve loaded category collection
*
* @return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = Mage::getModel('catalog/layer');
$bestsellers = Mage::getResourceModel('reports/product_collection');
if ($this->getTimeLimit()) {
$product = Mage::getModel('catalog/product');
$todayDate = $product->getResource()->formatDate(time());
$startDate = $product->getResource()->formatDate(time() - 60 * 60 * 24 * $this->getTimeLimit());
$bestsellers->addOrderedQty($startDate, $todayDate, true);
} else {
$bestsellers->addOrderedQty('', '', true);
}
$bestsellers->addStoreFilter()
->setOrder('ordered_qty', 'desc')
->setPageSize($this->getProductsLimit());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($bestsellers);
if ($layer->getCurrentCategory()->getId() != Mage::app()->getStore()->getRootCategoryId()) {
$bestsellers->addCategoryFilter($layer->getCurrentCategory());
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bestsellers);
}
if (!$this->isShowOutOfStock()) {
Mage::getModel('cataloginventory/stock')->addInStockFilterToCollection($bestsellers);
}
$bestsellers->getSelect()->where('order.store_id = ?', Mage::app()->getStore()->getId());
$productIds = array();
foreach ($bestsellers as $p) {
$productIds[] = $p->getId();
}
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
$collection->addIdFilter($productIds)
->addAttributeToSelect($attributes)
->addMinimalPrice()
->addFinalPrice();
$this->_productCollection = $collection;
}
return $this->_productCollection;
}
/**
* Translate block sentence
*
* @return string
*/
public function __()
{
$args = func_get_args();
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), 'Mage_Catalog');
array_unshift($args, $expr);
return Mage::app()->getTranslator()->translate($args);
}
}