PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Magento 2 produkt pokazuje „In Stock” przy qty=0 – niespójność MSI i legacy stock

by Henryk Tews / środa, 02 września 2026 / Opublikowano w Magento / Adobe Commerce

Produkt pokazywał „In Stock” na stronie produktu mimo że rzeczywiście nie było go na stanie. Klienci składali zamówienia na produkt który nie mógł zostać zrealizowany. Dopiero przy tworzeniu shipmentu pojawiał się błąd. Problem dotyczył produktów konfigurowalnych z MSI. Czas naprawy: 4 godziny.

Objawy

  • Produkt konfigurowalny pokazuje „In Stock” przy qty = 0 w panelu admin
  • Klienci mogą dodać do koszyka i złożyć zamówienie
  • Błąd przy tworzeniu shipmentu: „Not enough qty available”
  • W cataloginventory_stock_item: qty = 0, is_in_stock = 1
  • W inventory_source_item: quantity = 0, status = 1

Diagnoza

-- Sprawdź rozbieżność między starym a nowym systemem stock
SELECT
    csi.product_id,
    csi.qty as legacy_qty,
    csi.is_in_stock as legacy_status,
    isi.quantity as msi_qty,
    isi.status as msi_status,
    isi.source_code
FROM cataloginventory_stock_item csi
JOIN catalog_product_entity cpe ON cpe.entity_id = csi.product_id
JOIN inventory_source_item isi ON isi.sku = cpe.sku
WHERE csi.qty != isi.quantity
   OR csi.is_in_stock != isi.status
LIMIT 20;

-- Sprawdź salable quantity
SELECT sku, quantity
FROM inventory_stock_1   -- stock_id = 1 (default)
WHERE sku IN ('SKU-001', 'SKU-002');

Przyczyna

Import produktów aktualizował starą tabelę cataloginventory_stock_item ale nie tabele MSI (inventory_source_item). Po migracji na MSI stare API stocku jest tylko aliasem – prawdziwe dane są w tabelach inventory_*. Indekser cataloginventory_stock synchronizował dane w złym kierunku.

Rozwiązanie

<?php
// Poprawny sposób aktualizacji stocku w Magento 2 z MSI
use Magento\InventoryApi\Api\SourceItemsSaveInterface;
use Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory;

class StockUpdater
{
    public function __construct(
        private SourceItemsSaveInterface $sourceItemsSave,
        private SourceItemInterfaceFactory $sourceItemFactory,
    ) {}

    public function update(array $items): void
    {
        // $items = [['sku' => 'SKU-001', 'qty' => 50, 'source' => 'default'], ...]
        $sourceItems = [];
        foreach ($items as $item) {
            $sourceItem = $this->sourceItemFactory->create();
            $sourceItem->setSku($item['sku']);
            $sourceItem->setSourceCode($item['source'] ?? 'default');
            $sourceItem->setQuantity($item['qty']);
            $sourceItem->setStatus($item['qty'] > 0 ? 1 : 0);
            $sourceItems[] = $sourceItem;
        }
        $this->sourceItemsSave->execute($sourceItems);
        // MSI automatycznie zaktualizuje salable quantity i indeksy
    }
}
# Zsynchronizuj stary stock z MSI
bin/magento indexer:reindex cataloginventory_stock
bin/magento indexer:reindex inventory

# Uruchom kompensację rezerwacji jeśli są niespójności
bin/magento inventory:reservation:list-inconsistencies
bin/magento inventory:reservation:create-compensations

Wnioski

Po włączeniu MSI wszystkie operacje na stocku muszą używać API InventoryApi – nie starego cataloginventory. Stary interfejs działa jako wrapper ale tylko dla domyślnego źródła. Własne importery i integracje ERP wymagają aktualizacji do nowego API MSI.

About Henryk Tews

Co możesz przeczytać następne

Elasticsearch w Magento 2 – indeksowanie, debugowanie zapytań, własny analyzer dla polskiego
PWA Studio vs Hyvä vs Luma – rzetelne porównanie TCO i kiedy który
Magento 2.4.8 – PHP 8.4 wsparcie, migracja Elasticsearch → OpenSearch, checklist upgrade
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}