3

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?

1 Answer 1

2
+25

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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