Это довольно долго меня раздражало. В принципе, то, чего мы пытаемся достичь, находится в бестселлерах на нашей первой странице, чтобы продукты были перечислены в проданной сумме. Для простых продуктов это работает отлично, однако для конфигурируемых продуктов они будут отображаться как количество, упорядоченное по 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); } }
Спасибо, что опубликовали этот образец кода! Я смог использовать его для создания решения, которое должно хорошо работать для нас обоих.
Я обнаружил, что конфигурируемые продажи продукта суммируются правильно, но не включаются в результаты; вместо этого появляются их дочерние продукты. Мое решение состояло в том, чтобы включить настраиваемые продукты, сделать левое соединение в таблице 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
определяет, должны ли $getRemovedProducts
ранее заказываемые продукты (которые с тех пор были удалены из Magento). Обратите внимание, что для получения точных результатов статистика вашего отчета должна быть актуальной.
Надеюсь это поможет! Дайте знать, если у вас появятся вопросы.
Вы можете использовать следующий фрагмент кода, чтобы получить простые продукты, подключенные к настраиваемому продукту. Я не уверен, что это на 100% правильно, я сам не пробовал.
$simpleProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product);