Модуль Magento BestSeller - суммирование настраиваемых продуктов и добавление их обратно - PullRequest
3 голосов
/ 04 декабря 2011

Это меня давно беспокоило.По сути, мы стремимся добиться того, чтобы бестселлеры на нашей главной странице указывали продукты в продажной сумме.Для простых продуктов это работает нормально, однако для конфигурируемых продуктов они будут отображаться в количестве, указанном как 0.

Мне нужно как-то найти способ получить настраиваемые продукты, найти простые продукты, прикрепленные к ним, суммироватьколичество проданных этих простых продуктов, добавьте это обратно к идентификатору конфигурируемых продуктов и передайте эту информацию обратно, чтобы в нем был указан конфигурируемый продукт с нужным количеством, которое было продано.

Я разместил, что яПоверьте, области кода, которые требуют изменения.Если кто-то может помочь, это будет очень цениться!

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);
}
}

Ответы [ 2 ]

2 голосов
/ 07 декабря 2011

Спасибо за публикацию этого примера кода!Я смог использовать его для создания решения, которое должно работать хорошо для нас обоих.

Я обнаружил, что конфигурируемые продажи продукта суммируются правильно, но не включаются в результаты;вместо них появляются их дочерние продукты.Мое решение состояло в том, чтобы включить настраиваемые продукты, выполнить левое соединение с таблицей catalog_product_super_link и отфильтровать все, что имеет parent_id.Вот изменения, которые вам нужно сделать:

Collection.php:

    public function addOrderedQty($from = '', $to = '', $getComplexProducts=false, $getComplexChildProducts = true, $getRemovedProducts = true)
    {
        $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})",
                'order_items_name' => 'order_items.name'
            )
        );

         $_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()
         );

         // Add join to get the parent id for configurables
         $this->getSelect()->joinLeft(
             array('cpsl' => $this->getTable('catalog/product_super_link')),
             'cpsl.product_id = order_items.product_id',
             'cpsl.parent_id'
         );

        if(!$getComplexChildProducts)
            $this->getSelect()->having('parent_id IS NULL');

        if($getRemovedProducts)
        {
             $this->getSelect()
                ->joinLeft(array('e' => $this->getProductEntityTableName()),
                    "e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
                ->group('order_items.product_id');
        }
        else
        {
            $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');
        }


        $this->getSelect()->having('ordered_qty > 0');

        // This line is for debug purposes, in case you'd like to see what the SQL looks like
        // $x = $this->getSelect()->__toString();

        return $this;
    }

List.php - Найти следующие две строки ...

$bestsellers->addOrderedQty($startDate, $todayDate, true);
$bestsellers->addOrderedQty('', '', true);

... и измените их на:

$bestsellers->addOrderedQty($startDate, $todayDate, true, false, false);
$bestsellers->addOrderedQty('', '', true, false, false);

В мои изменения добавлены два новых необязательных параметра, оба из которых по умолчанию имеют значение true, чтобы не нарушать существующую функциональность.

  • Если для $getComplexChildProducts установлено значение false, все дочерние элементы конфигурируемого продукта будут удалены из результатов.
  • $getRemovedProducts определяет, будут ли ранее заказанные продукты (которые впоследствии были удалены из Magento)также должно появиться.

Обратите внимание, что статистика вашего отчета должна быть обновленной для получения точных результатов.

Надеюсь, это поможет!Дайте мне знать, если у вас есть какие-либо вопросы.

0 голосов
/ 04 декабря 2011

Вы можете использовать следующий фрагмент кода, чтобы прикрепить простые продукты к настраиваемому продукту.Я не уверен, что это на 100% правильно, я сам не пробовал.

$simpleProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product);
...