Magento – Create Special Price page which shows Catalog price rules products

magento-1.7priceproductproducts-management

========= UPDATE =========

I accepted simonthesorcerer response, but it didn't work for me.

I found a free module you can get on this url: http://www.magentocommerce.com/magento-connect/thirty4+interactive/extension/841/catalog-sale-items

it works fine on CE 1.7.0.2 if you install it manually from here: http://freegento.com/magento-extensions/Thirty4_CatalogSale-0.6.3_ready2paste.tgz

Download, unzip and move the files in the folders into your magento installation.

Hope this gonna be useful to somebody!!

========= END OF UPDATE =========

I'm trying to make a special price page… After trying and retrying and after several fails, I came up with this:

I've created a file called: special.php into this path: app/code/local/Mage/Catalog/Block/Product/ with this code:

<?php
class Mage_Catalog_Block_Product_Special extends Mage_Catalog_Block_Product_List {
   function get_prod_count() {

      Mage::getSingleton('catalog/session')->unsLimitPage();
      return (isset($_REQUEST['limit'])) ? intval($_REQUEST['limit']) : 300;
   }

   function get_cur_page() {
      return (isset($_REQUEST['p'])) ? intval($_REQUEST['p']) : 1;
   }

   protected function _getProductCollection() {
        $todayDate  = Mage::app()->getLocale()->date()->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
        $tomorrow = mktime(0, 0, 0, date('m'), date('d')+1, date('y'));
        $dateTomorrow = date('m/d/y', $tomorrow);

        $collection = Mage::getResourceModel('catalog/product_collection');
        $collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());

        $collection = $this->_addProductAttributesAndPrices($collection)
        ->addStoreFilter()
        ->addAttributeToSort('entity_id', 'desc')
        ->addAttributeToFilter('special_from_date', array('date' => true, 'to' => $todayDate)) 
        ->addAttributeToFilter('special_to_date', array('or'=> array(0 => array('date' => true, 'from' => $dateTomorrow), 1 => array('is' => new Zend_Db_Expr('null')))), 'left')
        ->setPageSize($this->get_prod_count())
        ->setCurPage($this->get_cur_page());

        $this->setProductCollection($collection);
        return $collection;
   }
}
?>

after that

I've created a file called: special.phtml into this path: app/design/frontend/default/MY THEME NAME/template/catalog/product/ with this code:

<?php 
    $columnsCount = 3;
    if (($_products = $this->getProductCollection()) && $_products->getSize()): 
?>

<div class="category-products">
<ol class="products-grid"  style="list-style: none;">
    <?php $i = 0; foreach ($_products->getItems() as $_product): ?>
    <?php // if($i++%$columnsCount == 0) : ?><?php // endif; ?>
     <li class="item<?php if( ++$_iterator == sizeof($_productCollection) ): ?> last<?php endif; ?>">
            <?php // Product Image ?>
            <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image">
                <img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(300, 200); ?>" alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
            </a>

            <div class="product-shop">
                <div class="f-fix">
                    <?php // Product Title ?>
                    <h2 class="the-product-manufacturer-grid"><a href=""><?php echo $_product->getAttributeText('manufacturer') ?></a><span class="the-product-name-grid"> / <a class="product-name" href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->htmlEscape($_product->getName()) ?>)"><?php echo $this->htmlEscape($_product->getName()) ?></a></span></h2>

                    <?php // Product Price ?>
                    <div class="listpricebox"><?php echo $this->getPriceHtml($_product, true, $this->getPriceSuffix()) ?></div>
                </div>
            </div>
    </li>
    <?php // if($i%$columnsCount == 0 || $i == count($_products)): ?><?php // endif; ?>
    <?php endforeach; ?>
</ol>
</div>

<script type="text/javascript">decorateGeneric($$('.grid-row'), ['first', 'last', 'odd', 'even']);</script>
<?php endif; ?>

and finally I'm calling all this stuff into a CMS page

{{block type="catalog/product_special" template="catalog/product/special.phtml"}}

now, everything is working fine except the fact that this page only shows products with a special price set one-by-one by editing the product. But the biggest part of my products are made in sale via Catalog Price Rules Do somebody have an idea can I show both Catalog Price Rules products and "Special Price" Products?

====== UPDATE ======

Here's the code

<?php
class Mage_Catalog_Block_Product_Special extends Mage_Catalog_Block_Product_List {

   protected function _getProductCollection() {
        // we need the date to filter for the special price
    $dateToday = date('m/d/y'); 
    $tomorrow = mktime(0, 0, 0, date('m'), date('d')+1, date('y'));
    $dateTomorrow = date('m/d/y', $tomorrow);

// this gets the product collection and filters for special price;
// grabs products with special_from_date at least today, and special_to_date at least tomorrow
        $_productCollection = Mage::getModel('catalog/product')->getCollection()
            ->addAttributeToFilter('special_from_date', array('date' => true, 'to' => $dateToday))
            ->addAttributeToFilter('special_to_date', array('date' => true, 'from' => $dateTomorrow))
            ->load();

// this loads the standard magento catalog proce rule model
        $rules = Mage::getResourceModel('catalogrule/rule_collection')->load();

// read: if there are active rules
        if($rules->getData()) {
            $rule_ids = array(); // i used this down below to style the products according to which rule affected
            $productIds[] = array(); // this will hold the ids of the products

            foreach($rules as $rule) {
                $rule_ids[] = $rule->getId();
                $productIds = $rule->getMatchingProductIds(); // affected products come in here
            }

// merge the collections: $arr is an array and keeps all product IDs we fetched before with the special-price-stuff
            $arr = $_productCollection->getAllIds();
            if($productIds) {
                // if there are products affected by catalog price rules, $arr now also keeps their IDs
                $arr = array_merge($arr,$productIds);
            }

// we initialize a new collection and filter solely by the product IDs we got before, read: select all products with their entity_id in $arr
            $_productCollection = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToFilter('entity_id',array('in'=>$arr))
                ->load();
        }
   }
}

Best Answer

it took me a while to figure this out. Should work for you, if you customy it for your needs.

To list products affected by a price rule, you must make your way over the rule-model.

Here is the code:

<?php
// we need the date to filter for the special price
    $dateToday = date('m/d/y'); 
    $tomorrow = mktime(0, 0, 0, date('m'), date('d')+1, date('y'));
    $dateTomorrow = date('m/d/y', $tomorrow);

// this gets the product collection and filters for special price;
// grabs products with special_from_date at least today, and special_to_date at least tomorrow
        $_productCollection = Mage::getModel('catalog/product')->getCollection()
            ->addAttributeToFilter('special_from_date', array('date' => true, 'to' => $dateToday))
            ->addAttributeToFilter('special_to_date', array('date' => true, 'from' => $dateTomorrow))
            ->load();

// this loads the standard magento catalog proce rule model
        $rules = Mage::getResourceModel('catalogrule/rule_collection')->load();

// read: if there are active rules
        if($rules->getData()) {
            $rule_ids = array(); // i used this down below to style the products according to which rule affected
            $productIds[] = array(); // this will hold the ids of the products

            foreach($rules as $rule) {
                $rule_ids[] = $rule->getId();
                $productIds = $rule->getMatchingProductIds(); // affected products come in here
            }

// merge the collections: $arr is an array and keeps all product IDs we fetched before with the special-price-stuff
            $arr = $_productCollection->getAllIds();
            if($productIds) {
                // if there are products affected by catalog price rules, $arr now also keeps their IDs
                $arr = array_merge($arr,$productIds);
            }

// we initialize a new collection and filter solely by the product IDs we got before, read: select all products with their entity_id in $arr
            $_productCollection = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToFilter('entity_id',array('in'=>$arr))
                ->load();
        }

== UPDATE ==

I added some comments to the code and renamed $skus to $productIds (which fits better).

If you are still getting errors, please let me know what's exactly happening. This code is tested for Magento v1.7.0.2.

Cheers
Simon

Related Topic