Question

Is it possible to get a product's final cart price? The products in the store I'm working on calculate pricing in a myriad of different ways, and rather than try to replicate the logic that decides which pricing method it uses, I thought it would be easier to just pretend the product was in the cart and use that price.

I know about $product->getFinalPrice(), but that's just one of the methods already being used on the site to display the price on the page. I'm hoping there exists a way to simulate a product already being in the cart, whether that's by creating a second, temporary cart to add it to, or some function I haven't yet found.

I already tried adding a product to the cart, getting the price, then removing it, but couldn't get $cart->removeItem($itemId) to work properly. Plus, that seems like a sloppy, unstable way to do that - I don't want to actually mess with the visitor's cart if I can help it.

Was it helpful?

Solution

I'm assuming you ask this because you want the benefit of all the sales rules which can be applied, inluding coupon codes and third-party logic that might come into play.

I have not exactly tried this before (except to test for this answer), but it makes sense to me that you would clone the visitor's quote, purge all items except the target, and recollect totals.

A solution might look like this:

require_once '/path/to/app/Mage.php';
Mage::app()->setCurrentStore(1);

$quote  = Mage::getSingleton('checkout/cart')->getQuote();
// Or load a specific model
//$quote  = Mage::getModel('sales/quote')->load(35);

$clone  = clone $quote;
$target = $clone->getItemsCollection()->getItemByColumnValue('product_id', 1);
// Or mock an item from another product in the catalog
//$product = Mage::getModel('catalog/product')->load(258);
//$target  = new Varien_Object(array('product' => $product, 'buy_request' => '1'));

$clone->getBillingAddress();
$clone->getShippingAddress()
    ->unsCachedItemsNominal()
    ->unsCachedItemsNonnominal()
    ->unsCachedItemsAll();

$clone->unsEntityId()
    ->removeAllItems()
    ->unsItemsCollection()
    ->setIsSuperMode(true);

$target->isDeleted(false);

$result = $clone->addProduct($target->getProduct(), $target->getBuyRequest());

$clone->setTotalsCollectedFlag(false)
    ->collectTotals();

foreach ($clone->getAllVisibleItems() as $item) {
    var_dump(
        "{$item->getSku()} x {$item->getQty()} = $" . ($item->getRowTotal() - $item->getDiscountAmount())
    );
}

var_dump($clone->getGrandTotal());

I won't do too much to unpack this, as it seems like you're already advanced enough to trace these lines back into the core for details.

What I will give you are some general comments:

  • Goal is to clone current quote but sever all ties to DB representation
  • We clear all items and add the desired/replace one existing
  • We do any housekeeping required to reset quote state for totals collection
  • We check our item totals (note use of row_total and discount_amount)
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top