How can I create a sales rule that applies a further reduction on special prices?
-
16-10-2019 - |
Question
Our catalog extensively uses 'Special Price' prices throughout. We need to put on a sale with 'further reduction' of 15% with this as a catalog price rule.
If the product was £10 and marked down to £5 by 'special price' then we would want to show a further 15% discount and see £4.25 (rather than £5 or £8.50).
As a workaround I can get the prices in and out of Excel, however, this 'further reduction' is a feature of the store and retail in general. Therefore, how do I do it? Using a cart rule is not what is needed here, I know I could apply a further reduction that way but I need the price to be actually paid on the front end.
Solution
You must rewrite /app/code/core/Mage/CatalogRule/Model/Resource/Rule.php class. There is function _getRuleProductsStmt returns product price data with sql query. I added some changes:
$specialAttr = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'special_price');
$specialTable = $priceAttr->getBackend()->getTable();
$specialId = $specialAttr->getId();
$specialCondition = '%1$s.entity_id=rp.product_id AND (%1$s.attribute_id=' . $specialId. ') and %1$s.store_id=%2$s';
//some code here
$select->joinLeft(
array('psp_default'=> $specialTable),
sprintf($specialCondition, 'psp_default', Mage_Core_Model_App::ADMIN_STORE_ID),
array('default_price'=> 'least(ifnull(psp_default.`value`,pp_default.`value`),pp_default.`value`)')
);
See full method body with my changes:
protected function _getRuleProductsStmt($fromDate, $toDate, $productId = null, $websiteId = null)
{
$read = $this->_getReadAdapter();
/**
* Sort order is important
* It used for check stop price rule condition.
* website_id customer_group_id product_id sort_order
* 1 1 1 0
* 1 1 1 1
* 1 1 1 2
* if row with sort order 1 will have stop flag we should exclude
* all next rows for same product id from price calculation
*/
$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'));
if (!is_null($productId)) {
$select->where('rp.product_id=?', $productId);
}
/**
* Join default price and websites prices to result
*/
$priceAttr = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'price');
$priceTable = $priceAttr->getBackend()->getTable();
$attributeId = $priceAttr->getId();
$specialAttr = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'special_price');
$specialTable = $priceAttr->getBackend()->getTable();
$specialId = $specialAttr->getId();
$joinCondition = '%1$s.entity_id=rp.product_id AND (%1$s.attribute_id=' . $attributeId
. ') and %1$s.store_id=%2$s';
$specialCondition = '%1$s.entity_id=rp.product_id AND (%1$s.attribute_id=' . $specialId
. ') and %1$s.store_id=%2$s';
$select->join(
array('pp_default'=> $priceTable),
sprintf($joinCondition, 'pp_default', Mage_Core_Model_App::ADMIN_STORE_ID),
array()
);
$select->joinLeft(
array('psp_default'=> $specialTable),
sprintf($specialCondition, 'psp_default', Mage_Core_Model_App::ADMIN_STORE_ID),
array('default_price'=> 'least(ifnull(psp_default.`value`,pp_default.`value`),pp_default.`value`)')
);
if ($websiteId !== null) {
$website = Mage::app()->getWebsite($websiteId);
$defaultGroup = $website->getDefaultGroup();
if ($defaultGroup instanceof Mage_Core_Model_Store_Group) {
$storeId = $defaultGroup->getDefaultStoreId();
} else {
$storeId = Mage_Core_Model_App::ADMIN_STORE_ID;
}
$select->joinInner(
array('product_website' => $this->getTable('catalog/product_website')),
'product_website.product_id=rp.product_id ' .
'AND rp.website_id=product_website.website_id ' .
'AND product_website.website_id=' . $websiteId,
array()
);
$tableAlias = 'pp' . $websiteId;
$fieldAlias = 'website_' . $websiteId . '_price';
$select->joinLeft(
array($tableAlias=> $priceTable),
sprintf($joinCondition, $tableAlias, $storeId),
array($fieldAlias=> $tableAlias . '.value')
);
} else {
foreach (Mage::app()->getWebsites() as $website) {
$websiteId = $website->getId();
$defaultGroup = $website->getDefaultGroup();
if ($defaultGroup instanceof Mage_Core_Model_Store_Group) {
$storeId = $defaultGroup->getDefaultStoreId();
} else {
$storeId = Mage_Core_Model_App::ADMIN_STORE_ID;
}
$tableAlias = 'pp' . $websiteId;
$fieldAlias = 'website_' . $websiteId . '_price';
$select->joinLeft(
array($tableAlias => $priceTable),
sprintf($joinCondition, $tableAlias, $storeId),
array($fieldAlias => $tableAlias . '.value')
);
}
}
return $read->query($select);
}
My Magento version is 1.7.0.2, I didn't tested result deeply, but this changes give me correct result.