Question

I'm seeing an issue occur where the catalog price rules aren't getting applied when a new product is enabled and saved at the same time.

When I look in the CatalogRule module, I see that there is an observer on the catalog_product_save_commit_after event calling Mage_CatalogRule_Model_Observer::applyAllRulesOnProduct()

Digging in to the observer, I see it calls:

Mage::getModel('catalogrule/rule')->applyAllRulesToProduct($product);

Digging in to this method, it calls Mage_CatalogRule_Model_Resource_Rule::applyToProduct for each catalog price rule. This method either deletes the data in the db table catalog_rule_product_price for the product if the rule doesn't apply to it, or calls Mage_CatalogRule_Model_Resource_Rule::insertRuleData($rule, $websiteIds, $productIds) if the rule matches. The parameter $productIds is an array with product ids for the keys and arrays of website ids as the values.

It's in the insertRuleData method that things seem to break down. In the method the body is largely an if statement that executes two different paths depending on whether the catalog product flat tables are enabled. If they aren't enabled theres a foreach statement that uses the product id array in a way it seems it was intended:

foreach ($productIds as $productId => $validationByWebsite)

If the flat tables are enabled, the $productId array is used in a select statement that appears to be incorrect:

$selectByStore->where('p.entity_id IN (?)', $productIds);

You have to wind through a bit of code, but p is set in:

Mage_Rule_Model_Resource_Abstract::getProductFlatSelect()

array('p' => $this->getTable('catalog/product')) aka the db table catalog_product_entity

So, the resulting select statement is basically SELECT ... FROM catalog_product_entity WHERE entity_id in (...website_ids...), as the website ids are the contents of the $productIds array.

This select statement will return the wrong products and the catalogrule_product table never gets properly updated. There's an indexer that depends on catalog_rule_product to create the contents of catalog_rule_product_price

Looks to me like a core bug? Am I missing something?

If it is a bug, what's the best practice for fixing it - over-riding the resource model or editing the core (gasp)?

Was it helpful?

Solution

Magento support confirmed it's a core bug. In Mage_CatalogRule_Model_Resource_rule::insertRuleData at about line 247 the code:

if (count($productIds) > 0) {
   $selectByStore->where('p.entity_id IN (?)', $productIds);
}

Should be replaced by

if (count($productIds) > 0) {
   $selectByStore->where('p.entity_id IN (?)', array_keys($productIds));
} 

I would guess this will be fixed in the next minor point release due out late November 2013 (1.8.1 and 1.13.1).

Edit:

This was indeed patched in versions 1.8.1 and 1.13.1

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top