Magento 2: Многоуровневый навигационный ценовой фильтр не работает после применения пользовательской скидки на продукт

13

Я работаю над модулем скидок на товары. Я сделал это с помощью плагина и обозревателя. он отлично работает на странице продукта и на странице списка. Но ценовой фильтр не работает в соответствии с обновленной ценой продукта.

Вот мой код, который я использую, чтобы настроить цену.

Имя_вендора / ModuleName / и т.д. / 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>

Имя_вендора / ModuleName / и т.д. / 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>

Имя_вендор / ModuleName / наблюдатель / 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);
    }
}

Имя_вендора / 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%

Ценовой фильтр не работает со скидкой

Примечание: цена со скидкой находится на уровне клиента

Дхаирья Шах
источник
HI Если вы хотите дать скидку. Так что я предлагаю вам использовать «Правило каталожной цены»
Рави Сони
@ravi Soni Мы создали специальный модуль. мы не можем использовать правило цены каталога для этого.
Дайрйа Шах
@Rohan Использую ту же версию и она не работает.
Приянк
Я ищу решение почти 4 года без какого-либо решения, надеюсь, вы найдете его, основная проблема в том, что цены в многоуровневой навигации исходят прямо из таблицы, а вы меняете цену на лету
WISAM HAKIM
@ WISAMHAKIM Нет, нет правильного решения. Надеюсь, кто-нибудь из основной команды Magento сможет разобраться в этом и предложить какое-то решение :)
Priyank

Ответы:

5

Это не решение, но это может быть объяснение того, как работают ценовые фильтры. Это может помочь определить решение.

Цены, отображаемые в списке продуктов, взяты из catalog_product_index_priceтаблицы.
Если вы посмотрите на выбор, который получает список продуктов, вы увидите что-то вроде этого:

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 ...

в вашем случае это не работает, потому что вы меняете окончательную цену продукта на лету, когда продукт продается. Но в таблице индексов цен у вас все еще есть первоначальная цена.

Фактическая индексация происходит (по крайней мере, для простых продуктов) в Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice::reindex.
Я не могу полностью объяснить, что там происходит, но у вас есть что зацепить.

Метод prepareFinalPriceDataForTypeиз того же класса вызывается в начале процесса индексации.
Этот метод заканчивается тем $this->modifyPriceIndex($finalPriceTable);
, что вы можете зацепить его, создав класс модификатора цены и добавив его в список модификаторов цены.
Вы можете создать модификатор цены следующим образом:

<?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.
     }
}

Вы можете найти пример модификатора цены в Magento\CatalogInventory\Model\Indexer\ProductPriceIndexFilter. Это удаляет товары, отсутствующие на складе, из индекса цен, если вы решили скрыть товары, которых нет на складе.

Вы создали свой модификатор цены, теперь вам нужно присоединить его к существующему списку модификаторов цены.

Вы можете сделать это из вашего файла di.xml с помощью

<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>

Теперь вы должны иметь возможность изменять цены в таблице индексов по своему усмотрению, реализовав метод modifyPriceв классе выше.

Это все, что я получил.

Мариус
источник
Отличное объяснение. но это не работает для меня, потому что цена со скидкой на уровне клиента.
Дхаирья Шах,
1
Да. magento плохо сочетается с ценами на уровне клиентов. С другой стороны, вы можете использовать группы клиентов. Это может означать, что вы получите много групп, которые замедляют индексирование. К сожалению, у меня нет другого чистого решения. Или грязный в этом отношении.
Мариус
У меня нет решения, которое я искал. Но так как вы первыми ответили с некоторым объяснением потока, я хотел бы дать вам бонусные баллы.
Приянк
2

Как я понимаю, структура потока Magento 2: Когда мы создаем правило цены каталога и сохраняем и применяем это правило. После этого нам необходимо переиндексировать данные для обновления цены. В это время цена будет обновлена ​​на соответствующий товар и сохранена в catalog_product_index_priceтаблице.

Но, как я понимаю, эта структура потока модуля не изменяет коллекцию продуктов, которая была отрисована для многоуровневого фильтра навигации. Вы можете проверить здесь vendor/magento/module-catalog/Model/Layer.php функцию getProductCollection () . Итак, согласно логике плагина, вы просто обновляете значение, которое отображается на внешней стороне. Но вы не обновили значения полей final_price и min_price в этой коллекции продуктов (данные функции getProductCollection () ).

Вы также можете проверить ту цену, которая показывает ваши пользовательские скидки. Но товар не добавлен в корзину со скидкой. Так что я думаю, что это не полное решение.

Таким образом, вам нужно обновить final_price и min_price объекта коллекции, как обновляет это правило цены каталога.

Надеюсь, это будет полезно для вас.

Рохан Хапани
источник