Magento: how to get the price of a product with catalog rules applied
Asked Answered
T

4

19

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.

Tyson answered 30/12, 2012 at 18:42 Comment(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?Someone
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...Tyson
"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.)Someone
Yes, you are correct, just replace "must really" by "should" or "is probably easier if". Thanks for the input.Tyson
T
12

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.

Tyson answered 31/12, 2012 at 2:57 Comment(0)
G
20

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

Gutow answered 30/12, 2012 at 20:25 Comment(5)
Hi, thanks for the answer (I missed that website in my searches). That seems exactly what I need but it doesn't work: returned prices are the same as original prices (and it doesn't return any price at all if product is not affected by any rule, although the later could be easily solved). I'm looking at the code from Mage_CatalogRule_Model_Rule and associated classes, it seems to do what I want, but it doesn't. I also tried to flush cache, reindex, etc., but result is always the same. Thanks once again.Tyson
try to load the product beforehand $_product->load($_product->getId()) if this works, then you miss an attribute. DONT STOP hat this point. Look which attribute is missing and add it to the collection. the code you posted looks like view.phtml or something, then you can just change the attribute settings in the backend.Gutow
I tried to use this but I´m getting this error : Invalid method Mage_CatalogRule_Model_Rule::calcProductPriceRule Anything I can do there?Jamijamie
I would assume your magento version is too old. You can look it up in one of the magento mirror, e.g. github.com/OpenMage/magento-mirrorGutow
Even after filling up groupId, storeId this is not usable. Especially if you make use of "Stop Further Rule processing". The best solution is what from augsteyerBandeen
O
12

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())
Ora answered 31/12, 2012 at 0:12 Comment(1)
Thanks a lot. I had the problem that the Cronjob of the Lengow Feed Export extension didn't considered the catalog rules correctly for price export. After applied setCustomerGroupId() to the product instance it worked well. I think this solution is much better then to simulate store frontends by Mage::app()->loadAreaPart() etc.Fugere
T
12

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.

Tyson answered 31/12, 2012 at 2:57 Comment(0)
C
12

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;
}
Chant answered 23/4, 2013 at 23:11 Comment(1)
Although faken's answer is the correct way to do it. If you want to be a rebel, this does work.Incompetent

© 2022 - 2024 — McMap. All rights reserved.