Magento 2: Warstwowy filtr cen nawigacji nie działa po zastosowaniu rabatu na produkty niestandardowe

13

Pracuję nad modułem rabatu na produkty. Zrobiłem to za pomocą wtyczki i obserwatora. działa dobrze na stronie produktu i stronie listy. Ale filtr cen nie działa zgodnie ze zaktualizowaną ceną produktu.

Oto mój kod, którego używam do dostosowania ceny.

Nazwa dostawcy / nazwa modułu / 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;
    }
}

Zastosowano 20% zniżki

Filtr cen nie działa z obniżoną ceną

Uwaga: obniżona cena jest na poziomie klienta

Dhairya Shah
źródło
CZEŚĆ Jeśli chcesz dać zniżkę. Sugeruję więc skorzystanie z „Reguły ceny katalogowej”
Ravi Soni,
@ravi Soni Stworzyliśmy niestandardowy moduł. nie możemy do tego użyć reguły ceny katalogowej.
Dhairya Shah
@Rohan Używanie tej samej wersji i nie działa.
Priyank
Szukam rozwiązania od prawie 4 lat bez żadnego rozwiązania, mam nadzieję, że je znajdziesz, głównym problemem jest to, że ceny nawigacji warstwowej pochodzą bezpośrednio z tabeli, a Ty zmieniasz cenę w locie
WISAM HAKIM
@WISAMHAKIM Nie ma właściwego rozwiązania. Mam nadzieję, że jakiś facet z zespołu Magento może przyjrzeć się temu i zaproponować jakieś rozwiązanie :)
Priyank

Odpowiedzi:

5

To nie jest rozwiązanie, ale może być wyjaśnieniem, jak działają filtry cen. Może to pomóc w znalezieniu rozwiązania.

Ceny wyświetlane na liście produktów pochodzą z catalog_product_index_pricetabeli.
Jeśli spojrzysz na wybór, który pobiera listę produktów, zobaczysz coś takiego:

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

w twoim przypadku nie działa, ponieważ zmieniasz ostateczną cenę produktu w locie, gdy produkt jest wysyłany. Ale w tabeli indeksu cen nadal masz oryginalną cenę.

Rzeczywiste indeksowanie ma miejsce (przynajmniej dla prostych produktów) w Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice::reindex.
Nie potrafię w pełni wyjaśnić, co się tam dzieje, ale masz coś, na czym można się przyłączyć.

Metoda prepareFinalPriceDataForTypez tej samej klasy jest wywoływana na początku procesu indeksowania.
Ta metoda kończy się na: $this->modifyPriceIndex($finalPriceTable);
To jest coś, do czego możesz się podłączyć, tworząc klasę modyfikatora ceny i dołączając ją do listy modyfikatorów ceny.
Możesz utworzyć taki modyfikator ceny:

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

Przykład modyfikatora ceny można znaleźć w Magento\CatalogInventory\Model\Indexer\ProductPriceIndexFilter. Spowoduje to usunięcie produktów z magazynu z indeksu cen, jeśli ustawisz ukrywanie produktów z magazynu.

Utworzyłeś modyfikator ceny, teraz musisz dołączyć go do istniejącej listy modyfikatorów ceny.

Możesz to zrobić z pliku di.xml za pomocą

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

Teraz powinieneś być w stanie modyfikować ceny w tabeli indeksu według własnego uznania, wdrażając metodę modifyPricew powyższej klasie.

To wszystko co mam.

Marius
źródło
Świetne wyjaśnienie. ale to nie działa, ponieważ obniżona cena na poziomie klienta.
Dhairya Shah,
1
Tak. Magento nie gra dobrze z cenami na poziomie klienta. Z drugiej strony możesz korzystać z grup klientów. Może to oznaczać, że masz wiele grup, które spowolnią indeksowanie. Niestety nie mam innego czystego rozwiązania. Lub brudny z tego powodu.
Marius
Nie mam rozwiązania, którego szukałem. Ale ponieważ jako pierwszy odpowiedziałeś z wyjaśnieniem przepływu, chciałbyś dać ci punkty premiowe.
Priyank
2

Jak rozumiem strukturę przepływu Magento 2, kiedy tworzymy regułę ceny katalogowej oraz zapisujemy i stosujemy tę regułę. Następnie musimy ponownieindeksować dane w celu aktualizacji ceny. W tym czasie cena zostanie zaktualizowana na odpowiednim produkcie i zapisana w catalog_product_index_pricetabeli.

Ale, jak rozumiem tę strukturę przepływu modułu, nie modyfikuje tej kolekcji produktów, która była renderowana dla warstwowego filtru nawigacji. Możesz sprawdzić tutaj vendor/magento/module-catalog/Model/Layer.php funkcję getProductCollection () . Tak więc, zgodnie z logiką wtyczek, po prostu aktualizujesz wartość wyświetlaną z przodu. Ale nie zaktualizowałeś wartości pola final_price i min_price w tej kolekcji produktów ( dane funkcji getProductCollection () ).

Możesz także sprawdzić wyświetlaną cenę, która jest niestandardową zniżką. Ale produkt nie został dodany do koszyka z obniżoną ceną. Myślę więc, że to nie jest pełne rozwiązanie.

Musisz więc zaktualizować cenę końcową i cenę minimalną obiektu kolekcji, tak jak aktualizacja reguły ceny katalogowej.

Mam nadzieję, że ci się przyda.

Rohan Hapani
źródło