Solving Magento

Solutions for Magento E-Commerce Platform

by Oleg Ishenko

Magento Catalog Price Rules

Mage_CatalogRule is a core module tasked to provide automated catalog price management, which can be controlled by a set of conditions. These conditions define a subset of the catalog to which price rules apply. For each rule a date range can be set, within which the rule is used. Also rules can be set to apply for certain customer groups. Catalog rules are defined on a website level, i.e. if a website has several store views, a website catalog price rule will apply to them all.

The catalog price rule management interface is found in the shop administration back-end under Promotions => Catalog Price Rules. If you are using a test installation with sample data (which you can obtain here), you can already see several catalog rules in the grid. We will discuss one of them as an example. If you don’t have the sample data – you can create sample catalog rules as we go over them.

Rule Information

Click on the rule called “20 percent off selected Furniture”. As the name suggests, this rule reduces the price for some products from the furniture category by 20%. Let’s make an overview of the rule’s properties:

  • Rule Name – a required parameter containing a descriptive name of the rule.
  • Status – a required parameter that controls the active status of the rule. If set to false it will deactivate the rule regardless of the conditions’ applicability.
  • Websites – a required setting, which lists websites where the rule can be applied. If you are running a multi-website environment the list may contain more than one entry. Otherwise, there is only one – Main Website.
  • Customer Groups – rules can be used to control prices for different customer groups. If you are using the sample data, you’ll see that the “Retailer” group is not selected. So, if a customer belongs to this group, he will get a regular price. Select all groups if you want the rule to be universal.
  • From Date and To Date – these both parameters are optional and define a date range restricting the rule’s validity. Outside this range the rule will not be applied. If you provide empty values for these parameters, the date range will not be restricted.
  • Priority – If there are more than one rule that can be applied to a product, this property will affect the order in which the rules are applied. Since the sorting is in an ascending order, the higher value is assigned to this property, the lower priority the rule has. The property rule_id is also included into sorting, so if two rules have the same priority, the rule with a lower ID is applied first.

Rule Conditions

Next to the “Rule Information” you can see a “Conditions” tab. There you set parameters that define which products the rule applies to. In our example, the “20 percent off selected Furniture” rule, these parameters read: if a product has SKU equal to any of the three values: 384822, 349838, 1112.

A rule condition consists of two parts: a combining condition and one or several sub-conditions. The sub-conditions are tied together by a combining condition. In our example it is if ANY of these conditions are TRUE. You can change ANY to ALL and TRUE to FALSE. Thus, a combining condition can have one of these four forms:

  • If ALL of these conditions are TRUE
  • If ALL of these conditions are FALSE
  • If ANY of these conditions are TRUE
  • If ANY of these conditions are FALSE

You can set multiple sub-conditions by clicking the round + button. This will open a drop-down list with product attributes. Not every attribute can be used to generate rule conditions. First of all, the attribute property is_used_for_promo_rules must be set to 1. Additionally, the function Mage_Catalog_Model_Resource_Eav_Attribute::isAllowedForRuleCondition() sets the following prerequisites:

  • An attribute must be visible (attribute property is_visible must be equal 1).
  • The frontend_input property must be one of the following types: ‘text’, ‘multiselect’, ‘textarea’, ‘date’, ‘datetime’, ‘select’, ‘boolean’, ‘price’.

The Magento attribute model also contains a property called is_used_for_price_rules, which can be confusing. Despite what its name suggests, this property has no effect on an attribute’s ability to be listed in the catalog price conditions. In fact, I have not found any trace of this property being used for any purpose at all. There is an upgrade file in the Mage_Catalog module (mysql4-upgrade-1.4.0.0.24-1.4.0.0.25) that assigns the values of is_used_for_price_rules to attribute property is_used_for_promo_rules. This allows me to assume that the is_used_for_price_rules property had used to be employed before, but had been deprecated since Mage_Catalog module version 1.4.0.0.25.

You can create multiple-levels of sub-conditions by using a combining condition. Select “Condition combination” in the drop-down list and you will get a combining setting similar to the one at the top level. Under it you can add a new branch of attribute-based sub-conditions.

Sub-conditions come in form of “attribute name” + “operator” + “value”. The “operator” depends on the attribute type and can be:

  • is
  • is not
  • equals or greater than
  • equals or less than
  • greater than
  • less than
  • is one of
  • is not one of
  • contains
  • does not contain

For certain attributes only some of these operators make sense, like a boolean attribute status can make use of “is” and “is not” only. If you experiment with different attributes you’ll notice that the list of available operators changes according to the attribute’s type.

The system presents you with an input field for the condition’s value according to the attribute’s type. For datetime attributes you get a calendar date picker, for an attribute with a predefined set of options – a drop-down list, and for a numerical or a text attribute – a text input field.

Actions

Once you have defined the conditions, move on to the last tab, Actions. There you’ll see several settings, which, when combined, tell the system how to change the price when applying the rule.

The first setting is a drop-down list called Apply. It has four options, which are used by the Mage_CatalogRule module’s helper class to calculate the price:

public function calcPriceRule($actionOperator, $ruleAmount, $price)
{
    $priceRule = 0;
    switch ($actionOperator) {
        case 'to_fixed':
            $priceRule = min($ruleAmount, $price);
            break;
        case 'to_percent':
            $priceRule = $price * $ruleAmount / 100;
            break;
        case 'by_fixed':
            $priceRule = max(0, $price - $ruleAmount);
            break;
        case 'by_percent':
            $priceRule = $price * (1 - $ruleAmount / 100);
            break;
    }
    return $priceRule;
}

Thus, each of these options has the following effect:

  • To Fixed Amount: the product price is set to the $ruleAmount, or remains unchanged if the original price is less than $ruleAmount. If the original price is $100 and the rule amount is 90, then the resulting price is $90.
  • To Percentage of the Original Price: the product price is set as a percentage ($ruleAmount) of the original price. If the original price is $150 and the rule amount is 80 then the resulting price is $120.
  • By Fixed Amount: the product price is reduced by $ruleAmount, or set to zero if the subtraction produces a negative value. If the original price is $100 and the rule amount is 15 then the resulting price is $85.
  • By Percentage of the Original Price: the product price is set to the subtraction result of the original price and its percentage ($ruleAmount). If the original price is $150 and the rule amount is 15 then the resulting price is $127.5 (150 – (15*150/100))

The value selected in the “Apply” list is translated into the property simple_action of the rule model.

The next input field is Discount amount, whose value is used by the rule’s action when calculating the new price by assigning it to the $ruleAmount variable from the helper function. The input is required and accepts a valid decimal number. Its value is saved in the rule property discount_amount.

The drop-down list Enable Discounts to Subproducts presents you with an option to extend the new price calculation to sub-products, i.e. the child products of configurable products (grouped products also have children, but their price calculation is not affected by this option). Keep in mind that when catalog price rules are applied to the children of a configurable product, it is not the price of the simple product that is modified as the “original price”. Instead the system re-calculates pricing options, which are entered next to simple products in the configurable’s “Associated products” edit tab (we will see this setting in action later when discussing an example of a rule applied to a configurable product).

configurable_options

If you select “Yes” in the “Enable Discounts to Subproducts” drop-down list, two additional inputs will appear, Apply and Discount Amount, which are similar to those of the main rule action. They will be applied in the same manner to the pricing options of the sub-products. These inputs correspond to rule properties sub_simple_action and sub_discount_amount. The option selected in the ”Enable Discounts to Subproducts” list is saved into the sub_is_enable rule property.

The last option in the “Action” tab is Stop Further Rule Processing (rule property stop_rules_processing). As I’ve mentioned before, there may be a situation when multiple rules can be applied to the same product; and the order in which they are applied is defined by the rule property sort_order (defined in the input field “Priority” in the “Rule Information” tab). It is possible to stop the further rule processing by setting this property to yes. Then the rule with the highest priority (actually, with the lowest value in the sort_order property, 0 by default) or with the lowest rule_id is applied while the rest is ignored.

Applying Catalog Rules and Calculating Product Prices

Before catalog rules can have any effect on product prices, they must be applied. The module Mage_CatalogRule has a cronjob that is executed daily. This cronjob goes through all the active catalog rules, finds products that match their conditions and calculates prices for those products. Alternatively, this process can be started from the back-end: “Promotions” => “Catalog Price Rules” => “Apply Rules”. The process of applying rules is relatively complex and uses data from several tables.

The first step is to match products to rules. This task is performed by the rule resource model in method Mage_CatalogRule_Model_Resource_Rule::updateRuleProductData. Here the system calls the rule model’s methods to find products matching the rule’s conditions. Found products are stored together with rule properties in table catalogrule_product, which serves as an information source for further price calculations.

It is important to keep in mind that updating the rule-product relationships in the catalogrule_product table is performed not in a cronjob, but only if you either manually apply rules in the back-end, or a product is saved (including the case when products are imported via the Mage_ImportExport module). The cronjob that applies rules daily by calling Mage_CatalogRule_Model_Observer::dailyCatalogUpdate skips this step and performs price calculations assuming that the rule-product relationships are already present in the database. This actually makes sense: if you create a rule, you must apply it explicitly at least once rather than later find yourself in a situation where a rule was applied automatically without your concern.

With the rule-product matching done, price calculation can start. This task is performed by the rule resource model’s method Mage_CatalogRule_Model_Resource_Rule::applyAllRulesForDateRange($fromDate = null, $toDate = null, $productId = null), and prices affected by rules are saved in table catalogrule_product_price. For each price entry the system saves a validity date in column rule_date. This information is very important because this date is checked every time a price is requested.

Rules can be set active for a certain period of time. To comply with this condition the prices in table catalogrule_product_price are updated daily by a cronjob. The cronjob calls the module’s observer method Mage_CatalogRule_Model_Observer::dailyCatalogUpdate(), which calls the applyAllRulesForDateRange() of the rule’s resource model with no arguments. If you look into this method’s code, you’ll see that if no value is provided for the fromDate and toDate parameters, it is assumed that the prices are calculated for rules, which are valid on the current day from 00:00 to 24:00. Any old data (with rule_date in the past) is deleted. This guarantees that on any given day the table catalogrule_product_price contains prices modified only by those rules, which are active on that day.

As I’ve mentioned above, the prices are calculated for products, whose relationships to rules are defined in table catalogrule_product. This can be seen in the function Mage_CatalogRule_Model_Resource_Rule::_getRuleProductsStmt($fromDate, $toDate, $productId = null, $websiteId = null), which is called before the calculation iterations start:

$select = $read->select()
->from(array('rp' => $this->getTable('catalogrule/rule_product')))
->where($read->quoteInto('rp.from_time = 0 or rp.from_time <= ?', $toDate)
. ' OR ' . $read->quoteInto('rp.to_time = 0 or rp.to_time >= ?', $fromDate))
->order(array('rp.website_id', 'rp.customer_group_id', 'rp.product_id', 'rp.sort_order', 'rp.rule_id'));

This piece of code from the function _getRuleProductsStmt creates a Varien_Db_Select object, which builds a query of all products from table catalogrule_product. Any product, which had not been previously matched to a rule, is not included into the price calculation.

The populating of the catalogrule_product_price is performed for every website and for the date range defined in the applyAllRulesForDateRange function’s call (none of this function’s calls in Magento core supplies a specific range, therefore it is performed for the current day as per default). The data collected in this table is now available to event observers that modify product prices.

Catalog Rule Events and Observers

There are 9 events that the Mage_CatalogRule module reacts to. They can be divided into three categories:

Responses to product price requests. If the system asks for a product price, the observer will return an adjusted price if any of the existing rules apply. This group includes three events:

  1. catalog_product_get_final_price – this event is dispatched when a product type model’s method getFinalPrice is called. If the call takes place in the front-end, the observer reacts with its method Mage_CatalogRule_Model_Observer::processFrontFinalPrice. If the call is made from the back-end, the observer executes Mage_CatalogRule_Model_Observer::processAdminFinalPrice. The difference between the two methods lies in the fact that price rules can contain conditions that apply only in a specific website or to a certain customer group or groups. When processing a front-end request this information is obtained from the event details or from the customer session. In the back-end this data is extracted from the rule and product objects. Other than that, the process in both methods is similar – the rule resource model is tasked to fetch an adjusted price from the catalogrule_product_price table. Note that if the adjusted price is higher than the product’s current final price, the lower price is returned, i.e. the current final price remains unchanged.
  2. catalog_product_type_configurable_price – this event is dispatched when the system needs to calculate option prices for a configurable product. This happens either in the block class Mage_Catalog_Block_Product_View_Type_Configurable‘s method getJsonConfig() or in price model method Mage_Catalog_Model_Product_Type_Configurable_Price::getTotalConfigurableItemsPrice. In both cases a request for a price of an option of a configurable product is intercepted and the price is modified according to applicable catalog rules. We will discuss this process in an example later.
  3. prepare_catalog_product_collection_prices – this event is dispathed whenever the system must evaluate prices of products in a collection that is a part of a checkout quote or of a bundle product. If you search for this event’s name in the code, you’ll find that it is dispatched in two methods: Mage_Sales_Model_Resource_Quote_Item_Collection::_assignProducts and Mage_Bundle_Model_Product_Price::getTotalBundleItemsPrice. The event triggers the Mage_CatalogRule module’s observer method prepareCatalogProductCollectionPrices. This method goes through the collection’s products and fetches their rule-adjusted prices. The collection, however, is not modified. The prices are saved in the observer’s internal property _rulePrices, which becomes available to other event calls within the current request since the observer instantiated as a singleton. Note that quotes collect their item prices by calling methods of the price models of the underlying products, e.g. Mage_Catalog_Model_Product_Type_Price or Mage_Catalog_Model_Product_Type_Configurable_Price, and it is there where the events that modify prices are triggered.

The next group of events is Reactions to product data changes. These reactions include creating, importing, modifying products, and re-indexing products prices. In these cases the observer rebuilds product-rule relationships, re-populates the catalogrule_product_price table, and supplies adjusted prices to be included into the price index. The events are:

  1. catalog_product_save_after – whenever a product model is saved, Magento dispatches this standard event, which triggers the Mage_CatalogRule module’s observer method applyAllRulesOnProduct. This method engages the rule model and the rule resource model to generate relationships between the given product and all the rules in the system. After these matches have been found and saved in table catalogrule_product the system calculates adjusted prices for the product on the current day and saves them in table catalogrule_product_prices.
  2. The events catalog_product_import_finish_before and catalog_product_import_after do a similiar job for products imported via module Mage_ImportExport. The first event triggers a method that creates product-rule relationships, and the second one starts a process of applying rules to the imported products’ prices.
  3. prepare_catalog_product_price_index_table – this event is dispatched during the product price re-indexing process. After the indexed price is saved into the index table this events triggers an observer method, which updates the index table with catalog rule adjusted prices. Because of this fact it is important to make sure that the Mage_CatalogRule module’s cronjob, which calculates rule prices for the current day, is run before the daily product price indexer.
<jobs>
    <catalogrule_apply_all>
        <schedule>
            <cron_expr>0 1 * * *</cron_expr>
        </schedule>
        <run>
            <model>catalogrule/observer::dailyCatalogUpdate</model>
        </run>
    </catalogrule_apply_all>
</jobs>

As you can see from the snippet of the catalog rule module’s config.xml, the job runs every day at 1AM. The standard cron schedule for the product price indexing is 2AM, as defined in the Mage_Catalog module’s configuration:

<jobs>
    <catalog_product_index_price_reindex_all>
        <schedule>
            <cron_expr>0 2 * * *</cron_expr>
        </schedule>
        <run>
            <model>catalog/observer::reindexProductPrices</model>
        </run>
    </catalog_product_index_price_reindex_all>
</jobs>

Reactions to attribute model changes. This last event group is comprised of events that react to changes in attribute model data. If an attribute, which is already in use by a catalog rule, is changed in any way preventing it from being used by that catalog rule, the rule can no longer apply to product prices. The events are:

  1. catalog_entity_attribute_delete_after – deleting attributes, obviously, invalidates the rules that use them. Once an attribute is deleted, the system checks if it is employed in conditions of any rule. If such rule is found, the attribute is removed from its conditions, the rule is deactivated, and all the rules are applied again to invalidate any prices modified by that rule.
  2. catalog_entity_attribute_save_after – the system checks if the edited attribute still can be used for the rule, i.e. its property is_used_for_promo_rules is set to 1. If not, then the process is the same as when dealing with deleted attributes: remove the attribute from rule conditions, deactivate affected rules, re-apply all active rules.

Catalog Price Rules and Configurable Products

Before concluding the discussion on catalog price rules, let’s consider an example that should help us to understand how catalog rules are employed and what their effect is. I choose a configurable product for this demonstration, which will also make possible to get an insight into how option prices of configurable products are modified by the catalog rules.

Prices for configurable products are processed on two levels. First, a final price of the configurable product is requested and adjusted as the module’s observer reacts to the catalog_product_get_final_price event. The second level is the pricing options of the configurable product. The configurable options are comprised of sub-products. If there is a price set on a configurable option, it can be controlled by a price rule. Such price rule has to have its property ‘sub_is_enable“ active. The observer’s function responsible for applying catalog rules to configurable option prices is called Mage_CatalogRule::catalogProductTypeConfigurablePrice(Varien_Event_Observer $observer). To illustrate this let’s create a test rule and apply it to a configurable product. If you are using the sample data provided by Magento, look for a product with SKU ‘ecco’. This is a configurable product and it has a configurable attribute ‘size’ with 4 options: sizes 3, 4, 5, and 6. These options are represented by simple products with SKUs ‘ecco_3’, ‘ecco_4’, ‘ecco_5’, and ‘ecco_6’. Note that fields “Price” next to each option are empty, which means that no matter what option a customer selects, the price remains the same $159.99. This is how the product and its options look in the back-end:

ecco_no_option_prices

And this is how the product is presented in the front-end:

ecco_frontend_no_option_prices

Now, let’s create a rule to apply to this product. In the “Promotions” => “Catalog Price Rule” click on “Add New Rule” and enter the following values in the rules properties in the “Rule Information” tab:

  • Rule Name: “20% off ECCO”
  • Status: “Active”
  • Websites: select all
  • Customer Groups: select all
  • From Date and To Date: leave empty.
  • Priority: -1

In the tab “Conditions” set up the following: If ALL of these conditions are TRUE: SKU is ecco.

In the tab “Actions” choose “By Percentage of the Original Price” in the “Apply” list. Enter 20 into the “Discount Amount” field. Set “Enable Discount to Subproducts” to “Yes”, in the next “Apply” list select again “By Percentage of the Original Price” and enter 20 into the “Discount Amount” field. In the last list, “Stop Further Rule Processing” select “Yes”.

Click “Save and Apply”. Once the rule is applied, refresh the cache and reload the product page. You’ll notice that the old price of $159.99 now has a strike through and a “special price” of $127.99 is displayed below. However, when you select an option, the price does not change. The reason for that are missing option prices in the configurable product.

ecco_frontend_special_price_no_option_prices

As I’ve mentioned before, catalog rules are applied to option prices and not to the actual prices of sub-products. Let’s now add option prices to the configurable product. In the back-end, in tab “Associated Products” fill “Price” input fields of the “Shoe Size” options with the following values:

  • Option 3: 100
  • Option 4: 110
  • Option 5: 120
  • Option 6: 130

Leave the values in the drop-down list next to them set to “Fixed”. These setting means that whenever one of the shoe size options is selected, the base price of the product is increased by the option price. For example, if a customer selects size 4, the total price would be $(159 .99+ 110) = $269.99. So it is, of course, if no catalog price rule is applied. To observe the effect of a catalog price rule on our configurable product, save your changes, clear the cache, and reload the product page. You do not need to re-index prices or to re-apply catalog rule in this case – saving a product will trigger the Mage_CatalogRule module’s observer to do it automatically.

Now, in the product page you’ll see that the product option drop-down list contains option price information. Next to every option there is a number showing how the price will change if the option is selected. When no option is selected, the option list looks like this:

  • 3: +$80.00
  • 4: +$88.00
  • 5: +$96.00
  • 6: +$104.00

These values are equal 80% of the option prices we’ve entered into the configurable product. Select option 4 and the total price of the product changes to $215.99, which is 80% of the price of $269.99 for the same option without the catalog rule effect.

ecco_frontend_special_price_with_option_prices

We have covered an important topic of the catalog price rules in detail, I believe, sufficient for you to understand an correctly employ them. This function is quite powerful and can be used for almost any task that requires product price manipulations. If you need something more, for instance, an ability to adjust prices according to, say, a session flag set when a visitor arrives via a link in a newsletter promising action prices – feel free to write an extension of the Mage_CatalogRule module to implement this or any other functionality you need.

29 thoughts on “Magento Catalog Price Rules

  1. Hi,

    nice article, congratulation!!
    Thanks for sharing the info.

    Actually, I just spent one day to understand why the update of one product was taking 10s!
    it was exactly because of the observer applyAllRulesOnProduct.

    It’s stupid because even if you save the product without doing any update, this observer will do so many things and take ages.
    For instance, it will update all previous quotes linked to the updated product (several thousands in my case).

    UPDATE `sales_flat_quote` AS `t1`
    INNER JOIN
    (SELECT
    `t2`.`quote_id` AS `entity_id`
    FROM
    `sales_flat_quote_item` AS `t2`
    INNER JOIN `catalogrule_product_price` AS `t3`
    WHERE
    (t2.product_id = t3.product_id)
    GROUP BY `quote_id`) AS `t2` ON t1.entity_id = t2.entity_id
    SET
    `t1`.`trigger_recollect` = 1

    And this is done several times for 1 product update! , the more you have rules, the more time it will take.
    That’s also why my test server was so fast, there were no promotions configured 🙂

    To save the performance, I first removed a lot of the old quotes from sales_flat_quote.

    It helps a lot.

    But not enough, what about removing this observer?

    Or at least only for new product?
    Then will the daily job take care of this?

    assuming I’m ok if the new price is only taken into consideration at the end of the day.

    I’m also thinking about doing this in a background task.
    Is magento having this concept?
    Magento EMbedded ERP does. I will check if I can use their concept of background tasks for this purpose

    thanks anyway for your help

    Rod

    • Hi Rod,

      Thank you for complimenting on my article! I’ve run into some complications with catalog rules recently and this is a result of my research on that problem.

      Also thank you for pointing out the observer performance issue due to the quotes. This is actually a very valuable input! I’ve never experienced such problem, because my shops do not have to many quotes with promo products. But I can easily imagine such situation.

      As of a solution to that, I can’t really tell. Disabling the observer may have some negative effect as its functionality gets missed. I would carefully consider all possible scenarios first. What is really important is to make sure that new products get their relationships defined in the catalogrule_product table – which one of this observer’s task and which is not done automatically elsewhere. The calculation of the rule prices can be left to the cronjob. Depending on the server setup it is possible to configure the crons to run on a back-end server, keeping the load off the front-end. Anyway, there are many possible ways to improve performance of the observer in this case and it is hard to recommend anything particular.

      Thanks again for leaving the comment! I am glad this article was of help to you.

    • Rod,

      Did you ever find a solution to the slow down caused by the update to the sales_flat_quote? I’m seeing the same behavior, but not only is causing the system to be slow I’m also getting deadlocks associated with the update to the sales_flat_quote.

      Dana

  2. Hi there, your article describes quite well CPRs and configurable articles and in particular how prices on the super attributes work in connection with CPRs.

    Do you have any idea how to get this information out of the DB? I am after the SQL that would allow me to get a list of products with their subproducts and the effecitve prices for all customer_Group and store combinations?
    I know that this might be a tough ask … 🙂

  3. Sorry forgot to mention if you execute
    select cprice.entity_id as product_id, cprice.website_id as website_id, customer_group_id, tax_class_id, price, final_price, min_price, max_price, tier_price
    from catalog_product_index_price cprice ;

    then the min_ and max_price shown disregard the discount on the sub product.

  4. Pingback: Quick Tip: Magento Catalog Price Rules Don’t Work | Solving Magento

  5. Hi guys,
    I need an advice, please.
    I have setup catalogue price rules and the prices are shown properly within the categories and products pages, however once you add product to a card, the price is the original one, not the discounted. The same price is included in the invoice etc…
    Not sure what the problem is, I am using the latest Magento version 1.7.0.2…
    Any guidance will be appreciated.

    Thanks Vancho.

  6. Hey folks!

    I have a catalogue price rule set-up for my loyalty card customers which shows them a discount price for ALL products when they log-in with their ID.

    I want to set-up a 20% shopping cart voucher. The catch is when a loyalty card customer uses this voucher code, the 20% discount should be applied to the ORIGINAL price of the item and not the discounted price as defined in the catalogue price rules. How can I do this?

    Tried so many options and google searched, but unable to find a solution… basically I want to know from the above scenario how shopping cart price rules can over-ride catalogue price rules..

  7. Great article.
    I am searching for a way (extension or any other way) to implement Catalogue Price Rules to selected customers instead of per customer group (a customer can only belong to one group and there may be more product groups) or all customers.
    Goal: we are an IT distributor selling products/groups to resellers who not always have the same discounts on all products/groups. Using Shopping Cart Rules adds all discounts to one total.

    Hope you have more input as I am running out of options… 🙁

    Martin

    • Hi Martin,

      Such task is definitely not trivial and will require development of an extension that rewrites the rule model. Not only you will need to extend the model to support individual customers, but also have to look into how the rule is applied and make sure it works with customer accounts instead of groups.

  8. Hi,

    I want to apply promotions on simple (Child) product, means when i applied promotions on configurable product its working fine and it applied all of the associated simple products,
    But i want to apply promotion ecco_6 = 10%, ecco_7 = 12%, ecco_8 = 20%.

    is it possible in magento 1.7.0.2 version.

    Please let me know your feedback..

    Regards,
    Peeyush Jagtap

  9. Hi Oleg,

    Working with 1.8.1.0

    I can create a price rule % discount that works if all conditions are true.

    If I insert a condition > Product Attribute > Specific Category the price rule does not work?

    The specific categories that I am selecting in the condition have grouped products with simple products associated.
    Could it be the category > grouped association selection that is causing the price discount rule to fail?

    • I think I am correct in saying that the Catalog price rule only works for simple products and as I have no simple products in categories the rules will not apply to the group.

      I have just changed the simple product visibility in the back end to search and the price rule seems to work. I assume that the search setting must be somehow associated to the catalog for it to apply the rule?

      • Hi Daniel,

        Not exactly: catalog price rules can work only for products types that have price attributes. Grouped products have no prices themselves and use the combined prices of their associated products. But the latter have to be visible in catalog or search for the price rule to be applied to them.

  10. Hello Oleg,

    Nice tutorials! I am working with downloadable products and with links (3) that you can purchase separately. One of those 3 options (links) is more expensive then the base price by 60$. If I make a promotion rule for all products the discount applies on the base price but not on the 60$ option. Do you know why and how I can fix it?

    I did try with Enable Discount to Subproducts but still nothing.

    Thank you for your help.

  11. Hi Oleg,

    I concur, Great article! You mention the cron jobs that run daily for catlogue price rules. Does this mean cron jobs will not work properly on a Magento setup running on an IIS Windows server?

    Would explain why my catalogue price rules keep dropping out.

    Many Thanks!

  12. Pingback: Catalog Price Rules disappear overnight - DL-UAT

  13. I’m struggling with this: I want a catalog rule to apply to all products which are not in a certain category.
    I tried
    If all of the following conditions are False
    – category is 54

    I also tried
    If all of the following conditions are True
    – category is not 54

    Also tried to use “contains” instead of “is” and several other combinations.

    But it seems not to apply. When I use the same conditions for a shopping cart rule, it works fine. And when I use rules applying to all products in a category it also works fine.

    I’m using Magento 1.9

    • We are having the same problem. Worked fine in 1.7 but in 1.9 “Category is not” no longer works for catalog price rules, although everything else seems to be working fine…

  14. I am running CE v1.7.0.2 and I have promotions created recently if I select a Promotion -> Catalog Price Rule -> In this case $1.00 Off Original Price -> Conditions and select -> If ANY of these conditions are TRUE : SKU (or any other selection) it just causes the page to re-load to my Orders page (which is my selected default) I cant figure out why I cant select anything. It used to work great but I noticed that any promotion I look at does this. Any help pointing me in the right direction towards correcting this would be greatly appreciated.

    • My host had to fix the issue. Hopefully if anyone else has this problem their answer will help you out! –

      The reason it was redirected was not due to Sessions or cookies. The AJAX request to get the HTML for the new “rule” there was triggering a Mod Security rule, and because of this, Magento was performing a redirect because of the failed response from the server.

      I’ve disabled Mod Security for your domain, so that these issues will not continue to occur.

  15. Pingback: Best tutorials for Magento | Ken Nguyen

  16. Hello,
    This article really helped me to understand about Catalog price rules.
    I have a question.
    Currently, Minimum price between default special price(entered from prices form for product) and price after discount is applied through catalog price rule is considered.
    How can we force catalog price rule over default special price?
    It would be great if someone explains.

  17. Hi Oleg,

    You are very knowledgeable. I’m redeveloping this site in Magento. http://prosoccer.com
    The current site has a site wide discount of 10% off on anything that isn’t a sale item. Is there a way to set a rule that discounts the entire site and shows the retail price crossed out? I see in one of your other articles you would need to add all sku’s for this rule. This would be 30,000 some sku’s. Any insight would be appreciated.

  18. Hi Oleg and all,

    I have issue with catalog price rule, getting the rule is applied and price corectly calcultaed and displayed, but after midnight the price back to original price, then i applied the rules again and get the discounted price shown and old price crossed. But the next day the price back to original price again.

    Today i spent one day just to observe the cron job set in cpanel running or not and finaly be sure it is running by testing it running the cron.sh in ssh console. But i dont see any record in cron_schedule table that mentioning catalog rule or price rule. I will wait until midnight whether the issue of price rule become inactive still happen (i put empty for end date for the rule)

    Would you or somebody else please help by showing me what is causing the problem and how to correct it in the right way.

    Thank you,
    Bun

  19. Hi,

    probably worth to mention a possible reason why promotions are ALL disabled during a few hours starting at midnight!
    My Linux web servers and my databse servers are configured originally UTC.
    Magento is fully configured GMT+2 (Europe/paris).

    This cause a bug in magento that I have fixed.
    the script is configured to re-apply rules during the night, by default at 1am.
    catalogrule_apply_all

    The script calculateq prices for the current day, the previous day and the next day.
    ‘dates’ => $this->_connection->select()->union(
    array(
    new Zend_Db_Expr(
    ‘SELECT ‘ . $this->_connection->getDateAddSql(
    $this->_connection->fromUnixtime($time),
    -1,
    Varien_Db_Adapter_Interface::INTERVAL_DAY
    ) . ‘ AS rule_date’
    ),
    new Zend_Db_Expr(‘SELECT ‘ . $this->_connection->fromUnixtime($time) . ‘ AS rule_date’),
    new Zend_Db_Expr(
    ‘SELECT ‘ . $this->_connection->getDateAddSql(
    $this->_connection->fromUnixtime($time),
    1,
    Varien_Db_Adapter_Interface::INTERVAL_DAY
    ) . ‘ AS rule_date’
    ),
    )
    )

    this is from app/code/core/Mage/CatalogRule/Model/Action/Index/Refresh.php

    BUT, at 1am, let’s say the 25th, $this->_connection->fromUnixtime($time) will return the previous day (not today) because of UTC configuration on the DV server!
    Thus it means magento calculates the prices for:
    . 2 days ago
    . the day before,
    . today

    It means after the script, prices are correct for today (the 25th) but.. at midnight (the 26th) there is no price set for that day!!
    Price are reset till the script run again 🙂

    There are probably multiple options to solve that.
    Look at
    $timestamp = $coreDate->gmtTimestamp(‘Today’);

    this is the code that actually return “yersteday” because of the config instead of today…
    You can replace this to make sure it returns “today”.
    This is what I did quickly this night to fix.
    Another option without code change is to change the scheduling so, in my case, it starts at 2am (to cover the +2 hours difference between UTC).

    I didn’t do that beacsue I was afraid to break some dependencies with other cron, for instance this article mentionned
    catalog_product_index_price_reindex_all
    that has to happen after catalogrule_apply_all

    another option could be to change the Linux and DB timezone so they match the magento locale settings but I was again afraid about some kind of regression

    Hope it helps!
    Rod

Leave a Reply

Your email address will not be published. Required fields are marked *

Theme: Esquire by Matthew Buchanan.