0

I have applied several price cart rules, I would like to see those frontend rules that work as a filter for discounted products. Someone can help me?

1 Answer 1

0

For filter products by discount percentage follow below steps:

1.Create the registration.php file

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_DiscountFilter',
    __DIR__
);

2.Create the Vendor/DiscountFilter/etc/module.xml file

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_DiscountFilter">
        <sequence>
            <module name="Magento_Catalog"/>
            <module name="Magento_CatalogSearch"/>
            <module name="Magento_Swatches"/>
            <module name="Magento_ConfigurableProduct"/>
            <module name="Magento_Eav"/>
            <module name="Magento_Customer"/>
            <module name="Magento_Store"/>
            <module name="Magento_Backend"/>
            <module name="Magento_MediaStorage"/>
            <module name="Magento_Config"/>
            <module name="Magento_LayeredNavigation"/>
            <module name="Magento_Theme"/>
        </sequence>
    </module>
</config>

3.create the Vendor/DiscountFilter/etc/adminhtml/system.xmlfile

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Magento/Config/etc/system_file.xsd">
    <system>
        <tab id="discountFilter" translate="label" sortOrder="500">
            <label>Discount Filter</label>
        </tab>
        <section id="discountFiltered" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Settings</label>
            <tab>discountFilter</tab>
            <resource>Vendor_DiscountFilter::vendor_discountfilter</resource>
            <group id="discountFilterGroup" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Discount Filter</label>
                <field id="isEnableDisable" translate="label comment" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Enable</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
            </group>
        </section>
    </system>
</config>

4.create Vendor/DiscountFilter/etc/frontend/routes.xml file

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route frontName="discountfilter" id="discountfilter">
            <module name="Vendor_DiscountFilter"/>
        </route>
    </router>
</config>

5.Create Vendor/DiscountFilter/etc/config.xml file

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <discountFiltered>
            <discountFilterGroup>
                <isEnableDisable>1</isEnableDisable>
            </discountFilterGroup>
        </discountFiltered>
    </default>
</config>

6.create Vendor/DiscountFilter/etc/di.xml file

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Model\Layer\FilterList" type="Vendor\DiscountFilter\Model\Layer\FilterList" />
    <type name="Magento\Catalog\Model\Layer\FilterList">
        <plugin name="FilterDiscountList" type="Vendor\DiscountFilter\Model\Layer\FilterList" sortOrder="1" disabled="false"  />
    </type>
</config>

7.create Vendor/DiscountFilter/Model/Layer/Filter/Rating.php file

<?php
namespace Vendor\DiscountFilter\Model\Layer\Filter;

use Magento\Catalog\Model\Layer;
use Magento\Catalog\Model\Layer\Filter\AbstractFilter;
use Magento\Catalog\Model\Layer\Filter\DataProvider\PriceFactory;
use Magento\Catalog\Model\Layer\Filter\Item\DataBuilder;
use Magento\Catalog\Model\Layer\Filter\ItemFactory;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Phrase;
use Magento\Store\Model\StoreManagerInterface;

/**
 * Class Rating
 * @package Vendor\DiscountFilter\Model\Layer\Filter
 */
class Rating extends AbstractFilter
{
    /**
     * @var CollectionFactory
     */
    protected CollectionFactory $productCollectionFactory;
    /**
     * @var PriceFactory
     */
    private $dataProvider;

    /**
     * Rating constructor.
     * @param ItemFactory $filterItemFactory
     * @param StoreManagerInterface $storeManager
     * @param Layer $layer
     * @param DataBuilder $itemDataBuilder
     * @param CollectionFactory $productCollectionFactory
     * @param PriceFactory $dataProviderFactory
     * @param array $data
     * @throws LocalizedException
     */
    public function __construct(
        ItemFactory $filterItemFactory,
        StoreManagerInterface $storeManager,
        Layer $layer,
        DataBuilder $itemDataBuilder,
        CollectionFactory $productCollectionFactory,
        PriceFactory $dataProviderFactory,
        array $data = []
    )
    {
        parent::__construct($filterItemFactory, $storeManager, $layer, $itemDataBuilder, $data);
        $this->productCollectionFactory = $productCollectionFactory;
        $this->_requestVar = 'dis';
        $this->dataProvider = $dataProviderFactory->create(['layer' => $this->getLayer()]);
    }

    /**
     * @return mixed
     */
    public function getResetValue(): mixed
    {
        return $this->dataProvider->getResetValue();
    }

    /**
     * @param RequestInterface $request
     * @return $this|AbstractFilter
     */
    public function apply(RequestInterface $request)
    {
        $filter = $request->getParam($this->getRequestVar());
        if (!$filter || is_array($filter)) {
            return $this;
        }
        $filter = explode('-', $filter);
        list($from, $to) = $filter;
        $entity_id = [];
        $collection = $this->productCollectionFactory->create()
            ->addAttributeToSelect(array('sku', 'price', 'special_price', 'special_to_date', 'special_from_date'))
            ->addAttributeToFilter('special_price', array('notnull' => true));

        foreach ($collection as $product) {
            $price = $product->getPrice();
            if($product->getTypeId() == "bundle")
            {
                $price  = $product->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue() ;
            }
            $sprice = $product->getSpecialPrice();
            $sprice_from_date = $product->getSpecialFromDate();
            $sprice_to_date = $product->getSpecialToDate();
            if ($price > 0 && isset($sprice_from_date) && isset($sprice_to_date) && !empty($sprice_from_date) && !empty($sprice_to_date)) {
                if (time() >= strtotime($sprice_from_date) && time() <= strtotime($sprice_to_date)) {
                    $dis = ($price - $sprice) * 100 / $price;
                    if ($dis >= $from && $dis <= $to) {
                        $entity_id[] = $product->getId();
                    }
                }
            }
        }
        $this->getLayer()
            ->getProductCollection()
            ->addAttributeToFilter('entity_id', array('in' => ($entity_id)));
        return $this;
    }

    /**
     * @return Phrase
     */
    public function getName(): Phrase
    {
        return __('Discount');
    }

    /**
     * @return array
     */
    protected function _getItemsData(): array
    {
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();;
        $scopeConfig = $objectManager->create('\Magento\Framework\App\Config\ScopeConfigInterface');
        if ($scopeConfig->getValue('discountFiltered/discountFilterGroup/isEnableDisable')) {
            $facets = array(
                '0-20' => '<div class="rating-result"><span>' . __('1% to 20%') . '</span></div>',
                '21-40' => '<div class="rating-result"><span>' . __('21% to 40%') . '</span></div>',
                '41-60' => '<div class="rating-result"><span>' . __('41% to 60%') . '</span></div>',
                '61-80' => '<div class="rating-result"><span>' . __('61% to 80%') . '</span></div>',
                '81-100' => '<div class="rating-result"><span>' . __('81% to 100%') . '</span></div>',
            );
            if (count($facets) > 1) {
                foreach ($facets as $key => $label) {
                    $filter = explode('-', $key);
                    list($from, $to) = $filter;
                    $collection = $this->getLayer()->getCurrentCategory()
                        ->getProductCollection()
                        ->addAttributeToSelect(array('sku', 'price', 'special_price', 'special_to_date', 'special_from_date'))
                        ->addFieldToFilter('special_price', array('gt' => '5'));
                    $count1 = 0;
                    foreach ($collection as $product) {
                        $price = $product->getPrice();
                        if($product->getTypeId() == "bundle")
                        {
                            $price  = $product->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue() ;
                        }
                        $sprice = $product->getSpecialPrice();
                        $sprice_from_date = $product->getSpecialFromDate();
                        $sprice_to_date = $product->getSpecialToDate();
                        if ($price > 0 && isset($sprice_from_date) && isset($sprice_to_date) && !empty($sprice_from_date) && !empty($sprice_to_date)) {
                            if (time() >= strtotime($sprice_from_date) && time() <= strtotime($sprice_to_date)) {
                                $dis = ($price - $sprice) * 100 / $price;
                                if ($dis >= $from && $dis <= $to) {
                                    $count1++;
                                    array($product);
                                }
                            }
                        }
                    }

                    if ($count1 > 0) {
                        $this->itemDataBuilder->addItemData(
                            $label,
                            $key,
                            $count1
                        );
                    }
                }
            }
            return $this->itemDataBuilder->build();
        }
    }

    /**
     * @param $from
     * @param $to
     * @return array
     */
    public function getProduct($from, $to): array
    {
        $sku = [];
        $collection = $this->getLayer()
            ->getProductCollection()
            ->addAttributeToSelect(array('sku', 'price', 'special_price'))
            ->addAttributeToFilter('special_price', array('notnull' => true));
        foreach ($collection as $product) {
            $price = $product->getPrice();
            $sprice = $product->getSpecialPrice();
            $dis = ($price - $sprice) * 100 / $price;
            if ($dis >= $from && $dis <= $to) {
                $sku[] = $product->getId();
            }
        }
        return $sku;
    }
}

8.create Vendor/DiscountFilter/Model/Layer/FilterList.php file

<?php
namespace Vendor\DiscountFilter\Model\Layer;

use Magento\Framework\View\Element\Template\Context;
use Magento\Catalog\Model\Layer;
use Magento\Framework\ObjectManagerInterface;
/**
 * Class FilterList
 * @package Vendor\DiscountFilter\Model\Layer
 */
class FilterList
{
    /**
     * @var ObjectManagerInterface
     */
    private ObjectManagerInterface $objectManager;

    /**
     * FilterList constructor.
     * @param Context $context
     * @param ObjectManagerInterface $objectManager
     */
    public function __construct(
        Context $context,
        ObjectManagerInterface $objectManager
    )
    {
        $this->objectManager = $objectManager;
    }

    /**
     * @param Layer\FilterList $subject
     * @param \Closure $proceed
     * @param Layer $layer
     * @return array|mixed
     */
    public function aroundGetFilters(
        Layer\FilterList $subject,
        \Closure         $proceed,
        Layer            $layer
    )
    {
        $result = $proceed($layer);
        $result[] = $this->objectManager->create('Vendor\DiscountFilter\Model\Layer\Filter\Rating', ['layer' => $layer]);
        return $result;
    }
}

9.create Vendor/DiscountFilter/view/frontend/layout/default.xml file

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <css src="Vendor_DiscountFilter::css/discount-filter.css"/>
    </head>
</page>

10.create Vendor/DiscountFilter/view/frontend/web/css/discount-filter.css

.rating-result{
    display: inline-block;
    margin-top: -5px;
}
  • Then set the special price of the product from the "Advance Pricing" and check on frontend side.

NOTE: it's works with a special price only.

Discount Filter

Your Answer

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

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