Magento – Magento2 multi-store price-per-website: Wrong price indexed for configurable products

indexingmagento2multi-websitepricereindex

I have a multi-website Magento 2.1.0 CE installation, with 2 websites and different prices per-website. Prices are note related to each other, for the same product across the two websites.

In product listing pages (PLP), I keep seeing "as low as $55.55" for configurable prices, along with the correct prices, in non-default website 2, even though prices have been set correctly, all configurable children have the same prices $55.55 in website 1 (default) and $77.77 in website 2 (non-default). Configurable product itself has been priced accordingly, there are no special nor tier prices applied.

I've checked price attribute values in database, all prices are save correctly per-website. Checking the price index table, though, returns correct min_price and max_price for simple products but prices from the wrong website for the configurable products, which is causing the "as low as" issue in product listing pages.

No 3rd-party modules are affecting indexing (vanilla Magento).

Anyone had the same issue?

Best Answer

Painfully debugged Magento core code (log all queries and reviewed step-by-step), the issue is in:

vendor/magento/module-configurable-product/Model/ResourceModel/Product/Indexer/Price/Configurable.php line 192

$priceColumn = $this->_addAttributeToSelect($select, 'price', 'l.product_id', 0, null, true);

The fourth parameter to Magento\Catalog\Api\Data\ProductInterface\AbstractIndexer::_addAttributeToSelect() is supposed to the the store_id for the (non-default) price to join from the attribute "decimal" value table, instead Magento passes the hard-coded "0", which is causing default store (website) prices to be put in product price index for configurable products, for any website_id.

Quick&Dirty Solution:

Replace in vendor/magento/module-configurable-product/Model/ResourceModel/Product/Indexer/Price/Configurable.php line 192:

$priceColumn = $this->_addAttributeToSelect($select, 'price', 'l.product_id', 0, null, true);

with:

$select->join( ['sg' => $this->getTable('store_group')], 'sg.website_id = i.website_id', [] ); $priceColumn = $this->_addAttributeToSelect($select, 'price', 'l.product_id', 'sg.default_store_id', null, true);

This way, Magento will select the price for non-default websites from the correct associated value for the default store in those websites, instead of statically assigning the default website price to each result.

Don't forget to reindex:

php bin/magento indexer:reindex catalog_product_price

Proper solution:

Create a custom module and overload the Magento\ConfigurableProduct\Model\ResourceModel\Product\Indexer\Price\Configurable class with your own modified version (see Quick&Dirty Solution) using DI preference ({your module}/etc/di.xml).

Don't forget to specify that your module depends on Magento_ConfigurableProduct module in your etc/module.xml and composer.json files.

Related Topic