isAvailable() и isSalable() возвращают false для всех продуктов на интерфейсе, даже если они определенно продаются


Я только что завершил миграцию с M1 на M2 версии 2.3.5-p1.

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

Похоже, это связано с тем, что проверка $_product->isAvailable() всегда возвращает значение false в файле vendor/magento/module-catalog/view/frontend/templates/product/view/type/default.phtml.

Однако я трижды проверил все данные о продуктах и запасах в базе данных и все (запасы, сопутствующие товары и т.д.), безусловно, подходят для моих продуктов.

Я сделал все как обычно: переиндексировал, очистил кэш, удалил папки и т. Д. и т. Д.

Я даже сделал быстрый внешний скрипт, чтобы проверить, что продукты можно продавать программно, и они:

<?php

// ---------------------
// Config
// ---------------------
$sku     = "SOMESKU123";
$storeId = 1;
// ---------------------

// Get Object Manager
require __DIR__ . "/../app/bootstrap.php";
\Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

// Set Magento area to frontend
$objectManager->get("Magento\Framework\App\State")->setAreaCode("frontend");

// Ensure correct store view is set
$storeManager = $objectManager->get("Magento\Store\Model\StoreManagerInterface");
$storeManager->setCurrentStore($storeId);

// Get product data
$myHelper = $objectManager->get("MyModule\MyFunctions\Helper\Data");
$product  = $objectManager->get("\Magento\Catalog\Model\ProductFactory")->create()->loadByAttribute("sku", $sku);

echo "\n Magento area code: " . $objectManager->get("\Magento\Framework\App\State")->getAreaCode();
echo "\n Product Name: "      . $product->getName();
echo "\n isSalable: "         . $product->isSalable();
echo "\n isAvailable: "       . $product->isAvailable();
echo "\n isInStock: "         . $product->isInStock();

Вывод вышеупомянутого скрипта, когда я запускаю его на том же экземпляре Magento 2:

Area code: frontend
Name: Whatever Product
isSalable: 1
isAvailable: 1
isInStock: 1

Но когда я загружаю тот же продукт на "настоящий" интерфейс Magento 2, он отображается как отсутствующий на складе и isAvailable() возвращает значение false.

Почему это должно было произойти?

Обновление

Я сделал больше отладки. Оказывается, есть много файлов, участвующих в отображении состояния запасов на странице продукта:

vendor\magento\module-catalog\view\frontend\templates\product\view\type\default.phtml
vendor\magento\module-catalog\Model\Product.php
vendor\magento\module-configurable-product\Model\Product\Type\Configurable.php
vendor\magento\module-catalog\Model\Product\Type\AbstractType.php
vendor\magento\module-catalog\Model\ProductRender.php
vendor\magento\module-catalog-inventory\Observer\AddInventoryDataObserver.php
vendor\magento\module-catalog-inventory\Helper\Stock.php
vendor\magento\module-catalog-inventory\Model\StockRegistryStorage.php
vendor\magento\module-inventory-catalog\Plugin\CatalogInventory\Helper\Stock\AdaptAssignStatusToProductPlugin.php
vendor\magento\module-inventory-catalog\etc\di.xml
vendor\magento\framework\Interception\Interceptor.php
vendor\magento\module-inventory-catalog\Plugin\InventorySalesApi\StockResolver\AdaptStockResolverToAdminWebsitePlugin.php
vendor\magento\module-inventory-configurable-product\etc\frontend\di.xml

Однако я считаю, что проблема связана с функцией assignStatusToProduct, которая расширяется функцией aroundAssignStatusToProduct внутри vendor/magento/module-inventory-catalog/Plugin/CatalogInventory/Helper/Stock/AdaptAssignStatusToProductPlugin.php.

Если я изменю framework/Interception/Interceptor.php и добавлю хак, чтобы эффективно пропустить вышеупомянутый плагин, начнет отображаться состояние запасов обычно:

public function ___callParent($method, array $arguments)
{
    // Begin hack
    if ($method == "assignStatusToProduct") {
        return;
    }
    // End hack

    return parent::$method(...array_values($arguments));
}

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

Кроме того, это дикое предположение, но причина, по которой эта проблема возникает только на интерфейсе Magento (а не через мой PHP-скрипт выше), может заключаться в том, что это функция вставляется с помощью инъекции зависимостей (module-inventory-catalog\etc\di.xml), которая может не вводиться, когда я вызываю ObjectManager непосредственно в своем скрипте.

Любые предложения приветствуются.

Author: WackGet, 2020-06-17

2 answers

Я публикую это как ответ, хотя это не ответ, а скорее обходной путь.

Похоже, что проблема возникает из-за инвентаризации нескольких источников, введенной в Magento 2.3. Вы можете увидеть подробную информацию о моих попытках отладки в обновлении моего вопроса выше, но вкратце: отключение модулей MSI остановило проблему.

Я отключил их, используя команду из этого ответа:

php bin/magento module:status | grep Magento_Inventory | grep -v List | grep -v None | grep -v -e '^$' | xargs php bin/magento module:disable

После выполнения этого (и setup:upgrade и т.д.) Продукты показывают обычно.

Интересно, что официальная документация Magento предполагает ...возможно, вам потребуется отключить модули управления запасами, чтобы ускорить процесс обновления для миграции продавцов....

Я не стал продолжать расследование, потому что я рад отключить MSI, но я подозреваю, что основная причина либо в том, что:

  • Возможно, мои продукты были неправильно назначены источнику запасов MSI; или
  • Возможно, источник по умолчанию вообще не существовал (вы можете проверить через Stores > Inventory > Source); или
  • Возможно, MSI не нравится, как были настроены мои продукты (настраиваемый артикул с Manage Stock: Yes, Stock Status: In Stock, Qty: 0 плюс сопутствующие детские товары с положительными количествами).
  • Возможно, в MSI есть ошибка (все, что я знаю, это то, что isSalable было установлено в 0 в плагине aroundAssignStatusToProduct, как я упоминал в ОП)

Мне также помогло следующее:

 3
Author: WackGet, 2020-06-19 01:03:03

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

enter image description here

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

php bin/magento module:disable –f Magento_Inventory Magento_InventoryAdminUi Magento_InventoryApi Magento_InventoryBundleProduct Magento_InventoryBundleProductAdminUi Magento_InventoryCatalog Magento_InventorySales Magento_InventoryCatalogAdminUi Magento_InventoryCatalogApi Magento_InventoryCatalogSearch Magento_InventoryConfigurableProduct Magento_InventoryConfigurableProductAdminUi Magento_InventoryConfigurableProductIndexer Magento_InventoryConfiguration Magento_InventoryConfigurationApi Magento_InventoryGroupedProduct Magento_InventoryGroupedProductAdminUi Magento_InventoryGroupedProductIndexer Magento_InventoryImportExport Magento_InventoryIndexer Magento_InventoryLowQuantityNotification Magento_InventoryLowQuantityNotificationAdminUi Magento_InventoryLowQuantityNotificationApi Magento_InventoryMultiDimensionalIndexerApi Magento_InventoryProductAlert Magento_InventoryReservations Magento_InventoryReservationsApi Magento_InventoryCache Magento_InventorySalesAdminUi Magento_InventorySalesApi Magento_InventorySalesFrontendUi Magento_InventoryShipping Magento_InventorySourceDeductionApi Magento_InventorySourceSelection Magento_InventorySourceSelectionApi Magento_InventoryShippingAdminUi Magento_InventoryDistanceBasedSourceSelectionAdminUi Magento_InventoryDistanceBasedSourceSelectionApi Magento_InventoryElasticsearch Magento_InventoryExportStockApi Magento_InventoryReservationCli Magento_InventoryExportStock Magento_InventorySetupFixtureGenerator Magento_InventoryDistanceBasedSourceSelection

Вы можете получить дополнительную информацию о его отключении с здесь ссылка

Или вы можете назначить свои продукты для инвентаризации с несколькими источниками, используя приведенный ниже код, который потребуется для всех продуктов

  $product_id = $product->getIdBySku("pbnddee");
  $_sourceItemsSaveInterface = $objectManager->get('Magento\InventoryApi\Api\SourceItemsSaveInterface');
  $_sourceItemFactory = $objectManager->create('Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory');
  $sourceItem = $_sourceItemFactory->create();
  $sourceItem->setSourceCode("default");
  $sourceItem->setSku(pbnddee);
  $sourceItem->setQuantity(10);
  $sourceItem->setStatus(1);
  $_sourceItemsSaveInterface->execute([$sourceItem]);

Надеюсь, мой ответ поможет

 2
Author: Kumar, 2020-06-18 07:59:13