Magento 2: le filtre de prix de navigation en couches ne fonctionne pas après la remise du produit personnalisé appliqué

13

Je travaille sur un module de réduction de produit. Je l'ai fait via un plugin et un observateur. cela fonctionne bien sur la page produit et la page liste. Mais le filtre de prix ne fonctionne pas selon le prix du produit mis à jour.

Voici mon code que j'utilise pour personnaliser le prix.

VendorName / ModuleName / 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;
    }
}

20% de réduction appliquée

Le filtre de prix ne fonctionne pas avec le prix réduit

Remarque: le prix réduit est au niveau du client

Dhairya Shah
la source
HI Si vous voulez donner un rabais. Je vous suggère donc d'utiliser la "Règle de prix catalogue"
Ravi Soni
@ravi Soni Nous avons créé un module personnalisé. nous ne pouvons pas utiliser la règle de prix catalogue pour cela.
Dhairya Shah
@Rohan Utilisation de la même version et ne fonctionne pas.
Priyank
Je cherche une solution depuis presque 4 ans sans aucune solution, j'espère que vous en trouverez une, le principal problème est que les prix dans la navigation en couches viennent directement du tableau, et vous changez le prix à la volée
WISAM HAKIM
@WISAMHAKIM Non, aucune solution appropriée. J'espère qu'un gars de l'équipe de base de Magento pourra examiner cela et suggérer une solution :)
Priyank

Réponses:

5

Ce n'est pas une solution, mais cela peut être une explication du fonctionnement des filtres de prix. Cela pourrait aider à identifier une solution.

Les prix affichés dans la liste des produits proviennent du catalog_product_index_pricetableau.
Si vous jetez un œil à la sélection qui récupère la liste des produits, vous verrez quelque chose comme ceci:

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

dans votre cas, cela ne fonctionne pas car vous modifiez le prix final du produit à la volée, lorsque le produit est affiché. Mais dans le tableau de l'indice des prix, vous avez toujours le prix d'origine.

L'indexation réelle se produit (au moins pour les produits simples) dans Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice::reindex.
Je ne peux pas expliquer complètement ce qui se passe là-dedans, mais vous avez quelque chose à quoi vous accrocher.

La méthode prepareFinalPriceDataForTypede la même classe est appelée au début du processus d'indexation.
Cette méthode se termine par $this->modifyPriceIndex($finalPriceTable);
C'est quelque chose que vous pouvez accrocher à l'achat en créant une classe de modificateurs de prix et en l'attachant à la liste des modificateurs de prix.
Vous pouvez créer un modificateur de prix comme celui-ci:

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

Vous pouvez trouver un exemple de modificateur de prix dans Magento\CatalogInventory\Model\Indexer\ProductPriceIndexFilter. Cela supprime les produits en rupture de stock de l'indice des prix si vous définissez de masquer vos produits en rupture de stock.

Vous avez créé votre modificateur de prix, vous devez maintenant le joindre à la liste existante des modificateurs de prix.

Vous pouvez le faire à partir de votre fichier di.xml avec

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

Vous devriez maintenant pouvoir modifier les prix dans la table d'index comme bon vous semble en implémentant la méthode modifyPricedans la classe ci-dessus.

C'est tout ce que j'ai.

Marius
la source
Grande explication. mais ça ne marche pas pour moi car le prix escompté au niveau client.
Dhairya Shah
1
Ouais. magento ne joue pas bien avec les prix au niveau des clients. D'un autre côté, vous pouvez utiliser des groupes de clients. Cela peut signifier que vous obtenez beaucoup de groupes qui ralentiront l'indexation. Malheureusement, je n'ai pas d'autre solution propre. Ou un sale d'ailleurs.
Marius
Je n'ai pas la solution que je cherchais. Mais puisque vous avez été le premier à répondre avec une explication du flux, vous aimeriez vous donner les points de prime.
Priyank
2

Si je comprends bien la structure de flux de Magento 2, lorsque nous créons une règle de prix de catalogue et enregistrons et appliquons cette règle. Après, nous devons réindexer les données pour le prix de mise à jour. À ce moment, le prix sera mis à jour sur le produit approprié et enregistré dans le catalog_product_index_pricetableau.

Mais, si je comprends bien la structure de flux de ce module, cela ne modifie pas la collection de produits qui était rendue pour le filtre de navigation en couches. Vous pouvez vérifier ici la fonction vendor/magento/module-catalog/Model/Layer.php getProductCollection () . Donc, selon la logique du plugin, vous mettez simplement à jour la valeur qui s'affiche sur le côté frontal. Mais, vous n'avez pas mis à jour la valeur du champ final_price et min_price dans cette collection de produits ( données de la fonction getProductCollection () ).

Vous pouvez également vérifier cet affichage de prix dont votre remise personnalisée. Mais, le produit n'a pas été ajouté au panier avec un prix discount. Donc, je pense que ce n'est pas une solution complète.

Donc, vous devez mettre à jour final_price et min_price de l'objet de collection comme la mise à jour de la règle de prix catalogue.

J'espère que cela vous sera utile.

Rohan Hapani
la source