草庐IT

php - Magento BestSeller 模块 - 汇总可配置产品并将它们添加回去

coder 2023-10-23 原文

这个问题困扰我好久了。基本上,我们正在努力实现的目标是在我们首页的畅销书上,让产品以销售量列出。对于简单的产品,这很好用,但是对于可配置的产品,它们将显示为订购数量 0。

我不知何故需要找到一种方法来获取可配置产品,找到附加到它们的简单产品,将这些简单产品的销售量相加,将其添加回可配置产品 ID 并将此信息反馈回去,这样它就会列出已售出的正确数量的可配置产品。

我认为,我已经放置了需要更改的代码区域。如果有人可以提供帮助,我们将不胜感激!

收藏.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;
}

}

列表.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 的内容。以下是您需要进行的更改:

集合.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 中删除)是否也应出现。

请注意,您的报告统计信息需要是最新的才能获得准确的结果。

希望对您有所帮助!如果您有任何问题,请告诉我。

关于php - Magento BestSeller 模块 - 汇总可配置产品并将它们添加回去,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8372453/

有关php - Magento BestSeller 模块 - 汇总可配置产品并将它们添加回去的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  6. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  7. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  10. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

随机推荐