We are developing a custom module which applies custom tier prices by product category. Our solution works on frontend checkout so far and consists of observing the sales_quote_item_set_product
event and running custom code that checks other quote items of a given category to apply a custom price.
The function responsible for applying the custom price to the item is below:
public function applyTierPrice($item, $tier)
{
$oldPrice = (float)$item->getProduct()->getPrice();
$newPrice = (float)$tier['discount'];
if ($tier['type'] === 'percent') {
$newPrice = $oldPrice - $oldPrice * ($tier['discount'] / 100);
}
$item->setCustomPrice($newPrice);
$item->setOriginalCustomPrice($newPrice);
$item->getProduct()->setIsSuperMode(true);
$item->save();
}
This solution becomes a problem on order creation by admin panel, because there is a field where you can set manually the item price, and apparently it also uses the methods setCustomPrice()
.
So, when we add a product to the quote, it runs the custom applyTierPrice()
method. But if I want to use that custom price field, our solution will override that field input, and we lose the default custom price functionality.
So i was thinking of a solution where we set the quote item price by calling $item->setPrice()
, and not messing with a custom price.
public function applyTierPrice($item, $tier)
{
$oldPrice = (float)$item->getProduct()->getPrice();
$newPrice = (float)$tier['discount'];
if ($tier['type'] === 'percent') {
$newPrice = $oldPrice - $oldPrice * ($tier['discount'] / 100);
}
// $item->setCustomPrice($newPrice);
// $item->setOriginalCustomPrice($newPrice);
$item->setPrice(42);
$item->getProduct()->setIsSuperMode(true);
$item->save();
}
$quote->collectTotals()
and $quote->save()
are being called after this function.
It updates the price field on the sales_flat_quote_item
table, but the change doesn't reflect on subtotal, row total, order total calculations.
How can I solve it? Any advice is appreciated.
edit1: applyTierPrice
method will not be called if there is a custom price filled.
Best Answer
Since the quote item price is retrieved by calling the
getFinalPrice
, we are overriding thegetFinalPrice
method.It's not a clean/final solution, but we managed partially solve our problem so far by overriding the
getFinalPrice
fromMage_Catalog_Model_Product_Type_Price
class. The custom code would be called only on quotes created by admin panel. The frontend quote (checkout) will continue using the quote item custom price.This solution have some problems, since we are overriding a method that is called multiple times during the quote proccess. To define the custom price we use the custom helper method
productCpdFinalPrice
, that iterates the quote items to define a custom price, and calling it from insidegetFinalPrice
would recursively callgetFinalPrice
again, leading to a infinite loop. Thats why I'm using the registry to avoid this behavior. The quote iteration in everygetFinalPrice
also leads to a slow performance of the quote processing. Also thegetFinalPrice
is defined in another classes like bundled producs, configurable, etc. We should override the method on those classes as well.And might exist other problems I didn't catch.
This is not the intended solution, but we're using this solution. It partially solved our problem.
Feedback is appreciated.