Fixing incorrect tier price with special price in Magento 2
There is a little nasty bug in Magento 2 which somehow survived till latest Magento 2 version (2.4.8 at the time of writing). The bug is that if you have set a regular price, then lower special price and then tier prices, the tier prices get calculated based on the regular price and not the special price. While this may not seem like a bug to everyone, in reality it affects the calculation of the lowest price possible.
THE BUG
Consider the following scenario (see figure below)
A product with:
- Regular price of $200
- Special price of $100
- All groups 20% discount if quantity is equal or larger than 3
The expected price if customer adds quantity of 3 in the cart would be 20% out of $100, however in reality the price is calculated 20% out of $200 (the regular price), thus resulting in $160 instead of expected $80 and this is wrong.
This is caused in Magento\Catalog\Model\Product\Attribute\Backend\Tierprice::modifyPriceData method (see below)
In here $price = $object->getPrice(); gets the regular product price and does not take into consideration that product might have a special price defined as well.
FIXING THE BUG
Unfortunately, modifyPriceData() method is a protected method and we can't fix this by defining an around() or after() plugin. The only possible solution would be to use a preference for Magento\Catalog\Model\Product\Attribute\Backend\Tierprice, this is not ideal because it may result in conflict with another extensions that could be doing the same thing but it's the only possible approach.
The steps to fix the bug include (the example here is from our Customer pricing extension for Magento 2 but you can do it in your own module as well):
1) Define a DI preference in vendor\anowave\price\etc\di.xml
With this we define a preference to override the modifyPriceData() method in our own class. It is important to use the etc/di.xml and not etc/frontend/di.xml because totals are calculated in the webapi_rest AREA and if you define this in the frontend area, the prefetence won't work at checkout where totals are calculated using API call.
2) Define a class that will override \Magento\Catalog\Model\Product\Attribute\Backend\Tierprice in Preference\Tierprice
This is a simple and quick way to fix the bug discussed in this quick article. If you don't feel like developing this yourself, you can check out our robust Price per Customer extension for Magento 2 which will do this fix for you. You can also benefit from a flexible customer pricing features for Magento 2 as well.