13

I working on a product discount module. I did it via plugin and observer. it's working fine on product page and list page. But price filter is not working according to the updated product price.

Here is my code which I am using to customise price.

VendorName/ModuleName/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Pricing\Price\FinalPrice">
        <plugin name="custom_discount_catalog_pricing_price_finalprice" type="VendorName\ModuleName\Plugin\FinalPrice" />
    </type>
</config>

VendorName/ModuleName/etc/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <event name='catalog_product_get_final_price'>
        <observer name='customdiscount_finalprice' instance='VendorName\ModuleName\Observer\ProcessFinalPrice'/>
    </event>
</config>

VendorName/ModuleName/Observer/ProcessFinalPrice.php

<?php

namespace VendorName\ModuleName\Observer;

use Magento\Framework\Event\ObserverInterface;

class ProcessFinalPrice implements ObserverInterface
{
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $product = $observer->getEvent()->getProduct();
        $old = $product->getData('final_price');
        $discountedPrice = $old - ($old * 0.20);
        $product->setData('final_price',$discountedPrice);
    }
}

VendorName/ModuleName/Plugin/FinalPrice.php

<?php

namespace VendorName\ModuleName\Plugin;

class FinalPrice
{
    public function afterGetValue(\Magento\Catalog\Pricing\Price\FinalPrice $subject, $result)
    {
        $discountedPrice = $result - ($result * 0.20);
        return $discountedPrice;
    }
}

20% Discount Applied

Price Filter Not Working With Discounted Price

Note: The discounted price is on customer level

  • HI If you want to give a discount. So I am suggesting you to use "Catalog Price Rule" – Ravi Soni Jun 28 at 6:56
  • @ravi Soni We have created a custom module. we can't use catalog price rule for that. – Dhairya Shah Jun 28 at 7:05
  • @Rohan Using the same version and its not working. – Priyank Aug 8 at 5:45
  • I am looking for a solution since almost 4 years without any solution, i hope you will find one, the main problem is the prices in the layered navigation are coming from the table directly , and you are changing the price on the fly – WISAM HAKIM Aug 10 at 1:25
  • @WISAMHAKIM Nope no proper solution. Hope some Magento core team guy can look into this and suggest some solution :) – Priyank Aug 12 at 9:14
5
+200

This is not an solution, but it may be an explanation of how the price filters work. This might help identify a solution.

The prices displayed in the list of products come from the catalog_product_index_price table.
If you take a look at the select that retrieves the product list you will see something like this:

SELECT 
  `e`.*, 
  `cat_index`.`position` AS `cat_index_position`, 
  `price_index`.`price`, 
  `price_index`.`tax_class_id`, 
  `price_index`.`final_price`, 
  IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, 
  `price_index`.`min_price`, 
  `price_index`.`max_price`, 
  `price_index`.`tier_price` 
FROM `catalog_product_entity` AS `e` 
INNER JOIN `catalog_category_product_index_store1` AS `cat_index` ON cat_index.product_id=e.entity_id AND ....
INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND ...

in your case, it does not work because you are changing the final price of the product on the fly, when the product is dispalyed. But in the price index table you still have the original price.

The actual indexing happens (at least for simple products) in Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice::reindex.
I cannot fully explain what happens in there, but you have something to hook onto.

The method prepareFinalPriceDataForType from the same class is called at the start of the indexing process.
This method ends with $this->modifyPriceIndex($finalPriceTable);
This is something you can hook into buy creating a price modifier class and attaching it to the price modifier list.
You can create a price modifier like this:

<?php
namespace Vendor\Module\Indexer\Price;

use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\PriceModifierInterface;
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructure;

class CustomPriceModifier implements PriceModifierInterface
{
     public function modifyPrice(IndexTableStructure $priceTable, array $entityIds = []) : void
     {
         //code here that modifies your price.
     }
}

You can find an example of price modiifier in Magento\CatalogInventory\Model\Indexer\ProductPriceIndexFilter. This removes the out of stock products from the price index if you set to hide your out of stock products.

You've created your price modifier, now you need to attach it to the existing list of price modifiers.

You can do that from your di.xml file with

<type name="Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\PriceInterface">
    <arguments>
        <argument name="priceModifiers" xsi:type="array">
            <item name="customPriceModifier" xsi:type="object">Vendor\Module\Indexer\Price\CustomPriceModifier</item>
        </argument>
    </arguments>
</type>

Now you should be able to modify the prices in the index table as you see fit by implementing the method modifyPrice in the class above.

That's all I got.

  • Great explanation. but It is not working for me because the discounted price on customer level. – Dhairya Shah Aug 8 at 10:22
  • 1
    yeah. magento does not play well with prices on customer level. On the other hand, you can use customer groups. This might mean that you get a lot of groups that will make indexing slower. Unfortunately I don't have another clean solution. Or a dirty one for that matter. – Marius Aug 8 at 11:50
  • Din't got the solution I was looking for. But since you were the first to answer with some explanation of flow would like to give you the bounty points. – Priyank Aug 16 at 6:10
2

As I understand Magento 2 flow structure, When we create catalog price rule and save & apply that rule. After, we must need to reindex data for update price. At that time, the price will be updated on the appropriate product and save in catalog_product_index_price table.

But, as I understand this module flow structure it's not modify that product collection which was render for layered navigation filter. You can check here vendor/magento/module-catalog/Model/Layer.php getProductCollection() function. So, as per plugin logic, you just update value which displays at the front end side. But, you didn't update final_price and min_price field value in that product collection (getProductCollection() function data).

You can also check that price display which your custom discount. But, the product did not add in cart with a discount price. So, I think it's not a full solution.

So, you need to update final_price and min_price of collection object as like catalog price rule update that.

Hope, it will be helpful for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.