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 непосредственно в своем скрипте.
Любые предложения приветствуются.
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
, как я упоминал в ОП)
Мне также помогло следующее:
Я предполагаю, что это связано с инвентаризацией с несколькими источниками, которая была добавлена в последнюю версию magento, чтобы проверить, правильно ли ваш продукт был отнесен к инвентаризации с несколькими источниками, вы можете перейти на серверную часть и взглянуть на это..
Вы можете проверить, отключив инвентаризацию с несколькими источниками, чтобы проверить, решит ли это вашу проблему, вы всегда можете включить ее, если это не так.
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]);
Надеюсь, мой ответ поможет