Question

product price is calculated dynamically based on certain conditions. while sorting with price it takes only default price not dynamically calculated price. the same issue with the price filter.

I can able to set the calculated price for product using event catalog_block_product_list_collection observer but not able to get products ordered by dynamic price.

<event name="catalog_block_product_list_collection">
    <observer name="product_price_change" instance="[vendor]\[module]\Observer\ProductCollectionDynamicPrice" shared="false" />
</event>

Observer - [vendor][module]\Observer\ProductCollectionDynamicPrice

<?php
namespace [vendor]\[module]\Observer;

use Magento\Framework\Event\ObserverInterface;

class ProductCollectionDynamicPrice implements ObserverInterface
{
    /**
     * set dynamic price
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @return $this
    */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
       $productCollection = $observer->getEvent()->getCollection();
       if ($productCollection instanceof \Magento\Framework\Data\Collection) {
          $productCollection->load();
          $this->calculatePrice($productCollection);
       }

       return $this;
    }

    /**
     * set dynamic calculated price to product collection
     *
     * @param ProductCollection $collection
     * @return $this
    */
    public function calculatePrice($collection) {

     foreach ($collection as $key => $item) {
        $price = 100;  // here my cuustom logic to calculate dynamic price based on conditions 
        $item->setMinPrice($price);
     }

     return $collection;

   }
 }

If I echoing min_price then able to get updated min_price but not able to get correct product orders collection sort by price.

Please anyone can help for the issue?

No correct solution

OTHER TIPS

I assume, In Category page you are trying to sort by the price and not getting the correct order while you want your prices to be displayed as well as used in sorting.

etc/frontend/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
        <plugin name="sortby_extend_default_sort_filters" type="Vendor\Module\Plugin\Toolbar" sortOrder="99" />
    </type>
</config>

Vendor\Module\Plugin\Toolbar

namespace Vendor\Module\Plugin;

use Zend\Filter\Boolean;
use Magento\Store\Model\StoreManagerInterface;

/**
 * Product list toolbar plugin
 */
class Toolbar
{
    protected $test;
    protected $storeManagerInterface;
    protected $_flag = true;

    public function __construct(StoreManagerInterface $storeManagerInterface)
    {
        $this->storeManagerInterface = $storeManagerInterface;
    }

    public function aroundSetCollection(\Magento\Catalog\Block\Product\ProductList\Toolbar $subject,
                                        \Closure $proceed,
                                        $collection
    )
    {
        $currentOrder = $subject->getCurrentOrder();
        $result = $proceed($collection);
        $pageSize = $collection->getPageSize();
        if ($pageSize) {
            $collection->clear();
        }
        if ($currentOrder && $currentOrder == 'price' && $this->_flag == false) {
            //Get current store information
            $currentStore = $subject->getCollection()->getStoreId();
            $currency = $this->storeManagerInterface ->getStore($currentStore)->getCurrentCurrencyCode();

            //add you custom calculation here in the result/collection
            $subject->getCollection()->getSelect()->columns(
                array(
                    'new_price' => new \Zend_Db_Expr("IF (
                    YOURCONDITION IN DB QUERY,
                    TRUE Value,
                    False Value)"))
            );
            //to reset sorting order 
            $subject->getCollection()->getSelect()->reset(\Zend_Db_Select::ORDER);
            $subject->getCollection()->getSelect()->order(new \Zend_Db_Expr('`new_price` ' . $subject->getData('_current_grid_direction')));
        }
        $this->_flag = false;
        return $result;
    }
}

You've to add your logic using SQL Query/Operators.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top