Magento – Do not apply catalog price rules on a product already on sale

catalogcatalog-price-rulesdiscount

We are runnning Magento EE 1.13.

We have a very large catalog (20 000 products) and 2000 categories.

We run a lot of sales but we do not use a sale category. We simply add a special price to the individual products which then show up as "on sale" in their respective categories.

We also have franchises(a customer group) that gets 30% discount on all products site-wide.

The problem we are facing is that the catalog price rules for franchises group(30% discount) applies to the already discounted price of sales on individual products eg :

  • Product default price is 100. Special price is 90 (for this specific product);
  • When a franchise logs in, the catalog price rule applies to the already discounted price of 90

We would like the franchises to get the 30% discount only on the original price and not on the special price.

How could I achieve this?

Best Answer

Your issue is that you need to be able to tell the rules that the special is current active.

I have had the same issue in my Dynamic Category Products Extension, in that I needed to allow date range attributes to consider the dates that the attribute is active on. To make it more complex, you would need to consider the date range set to be in range on the day the category (or in your case, the product) is viewed.

I thus came up with a new rule condition that is as such:

Product date range on day of viewing

Explaining how I did that would really take a bit of time, and the code is quite heavily integrated into the extensions code (as I added many other rule types)

What I can give you, and which you would be able to apply to any collection, is the way I altered the collection to filter out any products that are currently on special, taking into consideration the date range.

$collection is the actual product collection, as loaded from the current category. The block below is the code I use in the validation routine for product attributes, and some parts will be out of contect. Please ask if you need some bits/parts further explained.

Basically it ads in a filter to the product collection, that includes (or excludes) products that has active special price to form date ranges.

case 'date':
$todayDate = Mage::app()->getLocale()->date()->toString(Varien_Date::DATE_INTERNAL_FORMAT);
switch ($operator) {
    case 'inrange':
        //TO
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'null' => true
            ),
            array(
                'attribute' => $attrCode,
                'from' => $todayDate,
                //'to'      => $todayDate,
                'date' => true
            )
            )
        );
        // FROM
        $attrCodeFrom = str_replace('to', 'from', $attrCode);
        if (array_key_exists($attrCode, $this->_dropAtrribute)) {
            $attrCodeFrom = $this->_dropAtrribute[$attrCode];
        }
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCodeFrom,
                'null' => true
            ),
            array(
                'attribute' => $attrCodeFrom,
                //'from'    => $todayDate,
                'to' => $todayDate,
                'date' => true
            )
            )
        );
        // skip where both dates are null.
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'notnull' => true
            ),
            array(
                'attribute' => $attrCodeFrom,
                'notnull' => true
            )
            )
        );
        $collection->setFlag('applied_date_ranges_' . $attrCode, true);
        break;
    case 'ninrange': // inverted
        //TO
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'null' => true
            ),
            array(
                'attribute' => $attrCode,
                'to' => $todayDate,
                //'to'      => $todayDate,
                'date' => true
            )
            )
        );
        // FROM
        $attrCodeFrom = str_replace('to', 'from', $attrCode);
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCodeFrom,
                'null' => true
            ),
            array(
                'attribute' => $attrCodeFrom,
                //'from'    => $todayDate,
                'from' => $todayDate,
                'date' => true
            )
            )
        );
        // skip where both dates are null.
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'notnull' => true
            ),
            array(
                'attribute' => $attrCodeFrom,
                'notnull' => true
            )
            )
        );
        $collection->setFlag('applied_date_ranges_' . $attrCode, true);
        break;
    case 'xdaysago':
        $days = ($value == 1) ? 'day' : 'days';
        $startDate = date('Y-m-d', strtotime('-' . $value . ' ' . $days, strtotime($todayDate)));
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'gteq' => $startDate,
                'date' => true
            )
            )
        );
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'notnull' => true
            ),
            )
        );
        break;
    default:
        // all other date attributes
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                $operator => $value,
                'date' => true
            )
            )
        );
        $collection->addAttributeToFilter(
            array(
            array(
                'attribute' => $attrCode,
                'notnull' => true
            ),
            )
        );
        break;
}
break;

Hope this is of use to you. One day, when I have time, I'd like to extract that rule (and some others I created) and build a community module that extends core catalog rules. One day, when I have time!!

Related Topic