19
votes

I'm developing a script (external to Magento, not a module) which aims to output a text list of all available products, their prices and some other attributes. However, catalog price rules don't seem to be applied to product prices. If I use any of the following:

$_product->getPrice()
$_product->getFinalPrice()

I get the normal price (without rules being applied).

If I use:

$_product->getSpecialPrice()

I get null unless the product actually has a special price inserted in the product itself (i.e. if special price is not related with catalog rules).

I also tried

Mage::getModel('catalogrule/rule')->calcProductPriceRule($product,$product->getPrice())

as suggested in the answer given by Fabian Blechschmidt, but interestingly it returns the normal price only if the product is affected by any catalog rule, returning null otherwise.

There was a similar question in StackOverflow and Magento Forums some time ago, but the provided answer (which is to insert the code bellow) doesn't work for me (returned prices remain the same).

Mage::app()->loadAreaPart(Mage_Core_Model_App_Area::AREA_FRONTEND,Mage_Core_Model_App_Area::PART_EVENTS);

Does anybody have an idea of how to achieve this?

I'm using Magento 1.6.2.0. Thanks in advance.

4
Perhaps there is something else going on involving your data or indexing. Does the discounted price display as you expect in the default theme with all custom modules disabled?benmarks
Yes, the discounted prices display Ok in the frontend. The problem was that this was not a Magento module, but an "external" script. It seems Magento loads additional stuff which is required for everything to work properly. In other words, everything in Magento must really be a module...faken
"everything in Magento must really be a module" - Not really. There are however many modules which interact in many ways when the app is executing. I would check that Mage_CatalogRule_Model_Observer is instantiating. Perhaps you should paste the relevant parts of the remote script (Mage::app() instantiation, loadAreaPart() call, product load, etc.)benmarks
Yes, you are correct, just replace "must really" by "should" or "is probably easier if". Thanks for the input.faken

4 Answers

20
votes

Thanks to you, I found a new site: http://www.catgento.com/magento-useful-functions-cheatsheet/

And they mentioned:

Mage::getModel('catalogrule/rule')->calcProductPriceRule($product,$product->getPrice())

HTH

12
votes

As catalog price rules heavily depend on time, store and visiting customer, you need to set those parameters when you want to retrieve the product final price with it's price rules applied.

So, in your case, make sure that provided product is passed with the desired store and customer group id, which can be set as:

Mage::getModel('catalogrule/rule')->calcProductPriceRule($product->setStoreId('STORE_ID')->setCustomerGroupId('CUSTOMER_GROUP_ID'),$product->getPrice())
12
votes

I discovered the problem. The discounted prices display Ok in the store frontend. The problem was that I was developing a script "external" to Magento (thus not a Magento module), something like:

<?php

set_time_limit(0);
ignore_user_abort();
error_reporting(E_ALL^E_NOTICE);
header("Content-Type: text/plain; charset=utf-8");

require_once "app/Mage.php";

// Get default store code
$default_store = Mage::app()->getStore();
...

For everything to work properly it seems that one must follow the proper Magento bootstrap, and develop everything as a module. My script was so simple that I thought it wouldn't be necessary to code a complete module. In other words, everything in Magento should really be a module.

Concluding, using the module approach, all the methods work as expected:

$_product->getPrice()
$_product->getFinalPrice()
$_product->getSpecialPrice()

Thank you all for your input.

12
votes

This helped me in this issue: http://www.magentocommerce.com/boards/viewthread/176883/ . Jernej's solution seems plausible, but it does not handle rules that Overwrite other rules by using 'stop processing' and therefore can apply more than one rule.

$original_price = $_product->getPrice();
$store_id = 1; // Use the default store
$discounted_price = Mage::getResourceModel('catalogrule/rule')->getRulePrice( 
                        Mage::app()->getLocale()->storeTimeStamp($store_id), 
                        Mage::app()->getStore($store_id)->getWebsiteId(), 
                        Mage::getSingleton('customer/session')->getCustomerGroupId(), 
                        $_product->getId());

// if the product isn't discounted then default back to the original price
if ($discounted_price===false) {
    $discounted_price=$original_price;
}