Magento 2: Inventar programmgesteuert aktualisieren

11

Im folgenden Code kann ich alle Informationen unter Ausschluss der Bestandsdaten speichern. Hat sich in Magento 2 etwas geändert?

public function __construct(
    ScopeConfigInterface $scopeConfig, CollectionFactory $product,
    Magento\Catalog\Api\ProductRepositoryInterface $productRepository
) {
    $this->scopeConfig = $scopeConfig;
    $this->product = $product;
    $this->productRepository = $productRepository;
}

public function update(\XXXXXX\XXXXXX\Api\Data\InventoryCollectionInterface $data) {
    foreach ($data['list'] as $d) {
        $product = $this->productRepository->getById($d['entity_id']);
        $product->setStatus(($d['quantity'] > 0 ? 1 : 0));
        $product->setUpc($d['upc']);
        $product->setStockData(array(
            'qty' => $d['quantity'],
            'is_in_stock' => ($d['quantity'] > 0 ? 1 : 0)
        ));

        $this->productRepository->save($product);
    }

    return "Done";
}
Stephen Malenshek
quelle
1
Dies könnte helfen: github.com/magento/magento2/issues/5771
Mukesh Chapagain

Antworten:

32

Das funktioniert bei mir:

$item = ['qty' => 11]; // For example
$product->setStockData(['qty' => $item['qty'], 'is_in_stock' => $item['qty'] > 0]);
$product->save();

Bearbeiten :

Dies ist nicht mehr der richtige Weg, um damit $product->save()umzugehen , da es seit Magento 2.1 veraltet ist. Der richtige Weg, dies zu tun, ist die Verwendung von StockRegistryInterface:

/**
 * @var StockRegistryInterface
 */
protected $stockRegistry;

/**
 * Inventory constructor.
 * @param StockRegistryInterface $stockRegistry
 */
public function __construct(
    StockRegistryInterface $stockRegistry
)
{
    $this->stockRegistry = $stockRegistry;
    parent::__construct();
}

Mit dem obigen Code können Sie Folgendes verwenden:

$sku = 'ABC123';
$qty = 10;
$stockItem = $this->stockRegistry->getStockItemBySku($sku);
$stockItem->setQty($qty);
$this->stockRegistry->updateStockItemBySku($sku, $stockItem);

Verwenden Sie Manager so oft wie möglich. Halten Sie Ihre Module voneinander entkoppelt.

Es ist der Magento Way ™

Giel Berkers
quelle
setStockData ist erforderlich. Es ist nicht erforderlich, -> setQuantityAndStockStatuses aufzurufen, obwohl dies keinen Schaden zu verursachen scheint.
Robert Egginton
9
Es funktioniert gut für ein Produkt. Wenn Sie jedoch eine CSV-Datei mit 5k-SKUs lesen, ist die Leistung ziemlich schlecht. Hat jemand das gleiche Problem?
Medina
+1 für die Aktualisierung Ihres Beitrags auf Magento 2.1 Version.
ZFNerd
+1 für Best Practices (und Aktualisierung der Antwort)
Akif
Schätzen Sie wirklich die aktualisierte Methode! Magento wird für uns alle besser, weil Community-Mitglieder wie Sie solche Beiträge verfassen!
Weiter
16

Wenn Sie die @ giel-berkers-Lösung verwenden, müssen Sie möglicherweise auch isInStock festlegen, da diese nicht automatisch festgelegt wird. Der folgende Code war also nützlich für mich:

public function __construct(
    \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry
)
{
    $this->stockRegistry = $stockRegistry;
    parent::__construct();
}

public function yourMethod() {
    $sku = 'ABC123';
    $qty = 10;
    $stockItem = $this->stockRegistry->getStockItemBySku($sku);
    $stockItem->setQty($qty);
    $stockItem->setIsInStock((bool)$qty); // this line
    $this->stockRegistry->updateStockItemBySku($sku, $stockItem);
}
spiil
quelle
Wie kann ich diese Antwort verwenden, um die Menge in Magento 2 zu aktualisieren?
Mujahidh
@ Mujahidh Sie können versuchen, scopeId als zweiten Parameter an die getStockItemBySku()Methode zu übergeben
spiil
1
danke, die Menge wird aktualisiert, aber nicht speicherweise, da beide Geschäfte die gleiche Menge aktualisieren.
Mujahidh
8

Eine Sache, die die anderen Antworten übersehen haben, ist, dass wenn Sie setQty($qty), genau den Wert anwenden, den Sie angeben. Wenn jedoch ein Verkauf für dieses Produkt einen Moment vor dem Speichern durchgeführt wurde, könnte sich die ursprüngliche Menge geändert haben. Was Sie also wirklich tun möchten, ist Magento den Unterschied mitzuteilen, den Sie auf die Menge anwenden möchten.

Glücklicherweise bietet Magento 2 einen guten Mechanismus dafür. Schauen Sie sich an Magento\CatalogInventory\Model\ResourceModel\Stock\Item:

protected function _prepareDataForTable(\Magento\Framework\DataObject $object, $table)
{
    $data = parent::_prepareDataForTable($object, $table);
    $ifNullSql = $this->getConnection()->getIfNullSql('qty');
    if (!$object->isObjectNew() && $object->getQtyCorrection()) {
        if ($object->getQty() === null) {
            $data['qty'] = null;
        } elseif ($object->getQtyCorrection() < 0) {
            $data['qty'] = new \Zend_Db_Expr($ifNullSql . '-' . abs($object->getQtyCorrection()));
        } else {
            $data['qty'] = new \Zend_Db_Expr($ifNullSql . '+' . $object->getQtyCorrection());
        }
    }
    return $data;
}

Hier sehen wir, dass, wenn Sie den qty_correctionWert festlegen , die Differenz schrittweise angewendet wird, anstatt einen genauen Betrag anzuwenden.

Mein Vorschlag für eine sicherere Mengenersparnis lautet also:

/**
 * @var \Magento\CatalogInventory\Api\StockRegistryInterface
 */
protected $stockRegistry;

public function __construct(StockRegistryInterface $stockRegistry)
{
    $this->stockRegistry = $stockRegistry;
}

/**
* Set the quantity in stock for a product
*
*/
public function applyNewQty($sku, $newQty)
{
    $stockItem = $this->stockRegistry->getStockItemBySku($sku);
    $origQty = $stockItem->getQty();
    $difference = $newQty - $origQty;
    $stockItem->setQtyCorrection($difference);
    $this->stockRegistry->updateStockItemBySku($sku, $stockItem);

    // note that at this point, $stockItem->getQty() is incorrect, so you'll need to reload if you need that value
}
cyk
quelle
7

Ich hatte mit dem gleichen Problem zu kämpfen. Beim Debuggen habe ich festgestellt, dass die Produktdaten ein Array "Quantity_und_Stock_Status" haben. Deshalb habe ich versucht, Folgendes festzulegen:

$product->setQuantityAndStockStatus(['qty' => $quantity, 'is_in_stock' => 1]);

und es fing an, für mich zu arbeiten. Ich setze auch weiterhin $ product-> setStockData, wenn Sie ein Produkt bearbeiten und das Element in den Feldern untersuchen, in denen beide angezeigt werden. Eines befindet sich auf der Registerkarte "Allgemein", das andere in den Feldern für das erweiterte Inventar. Ich habe nicht vollständig untersucht, warum es zwei davon gibt.

Kevin Chavez
quelle
Art und einfach, sehr gute Lösung !!! arbeitet für mich +1
Manthan Dave
Bevorzugte Lösung, da dies funktioniert und viel weniger Bearbeitung
erfordert
Wenn das Produkt deaktiviert ist, wird die Menge nicht aktualisiert. Andernfalls funktioniert der Aktivierungsstatus ordnungsgemäß. Kannst du mir dabei helfen? Meine Seite ist in 2.1.9
Anil
1

Der folgende Code funktioniert einwandfrei, damit ich die Produktmenge aktualisieren kann.

public function __construct(
    \Magento\Catalog\Model\ProductFactory $productFactory
) {
    $this->productFactory = $productFactory;
}

public function updateQty(){
    $sku = '24-mb01';
    $product = $this->productFactory->create();
    $productId = $product->getIdBySku($sku);
    if($productId){
        $product->load($productId);
    }

    $product->setStockData(
        array(
            'use_config_manage_stock' => 0,
            'manage_stock' => 1,
            'is_in_stock' => 1,
            'qty' => 10
        )
    );

    try {
        $product->save(); 
        echo $sku.' updated. '; 
    } catch (Exception $e) {
        echo $e->getException();
    }
}
Rakesh Jesadiya
quelle
Wenn der Produktstatus deaktiviert ist, wird die Menge in meinem Fall nicht aktualisiert. Können Sie mir helfen, es zu lösen?
Anil
1
$objectManager = $bootstrap->getObjectManager();
$stockRegistry = $objectManager->create('Magento\CatalogInventory\Api\StockRegistryInterface');

$stockItem = $stockRegistry->getStockItemBySku($sku);
$stockItem->setQty($qty);
$stockItem->setIsInStock((bool)$qty);
$stockRegistry->updateStockItemBySku($sku, $stockItem);
MHK Entwickler
quelle
0

Versuchen Sie, StoreId vor allem auf $ product zu setzen, und ersetzen Sie möglicherweise:

$product->setStockData(...) zum $product->setData('stock_data', '...') // A Paranoid Recommendation

Übrigens: Wenn Sie sich den Save ActionController im Backend ansehen, verwendet M2 einen Filter zum Vorbereiten von stock_data. Sie finden diesen Filter in:

Magento \ Catalog \ Controller \ Adminhtml \ Product \ Initialization \ StockDataFilter

MauroNigrele
quelle
Ich schätze die Antwort, aber diese Option hat nicht funktioniert. Danke für die Hilfe.
Stephen Malenshek
0

Versuchen Sie dieses, während das Produkt im Admin - Speichern gespeichert sie Bestandsdaten von Ereignis mit catalog_product_save_after in Magento_CatalogInventoryModul Beobachter

Magento \ CatalogInventory \ Observer \ SaveInventoryDataObserver

saravanavelu
quelle
0

Ich hatte das gleiche Problem für Magento 2.0.9 und der folgende Code funktioniert in meinem Fall

$productStock = $this->_productRepository->getById($item->getMageproductId());
$productStock->setQuantityAndStockStatus(['qty' => 12, 'is_in_stock' => 1]);
$res = $productStock->save();
Nitin Pawar
quelle
0

Magento2 verfügt auch über eine Multi-Stock-Funktion. Um eine bestimmte Stock-Quelle zu aktualisieren, können Sie dieser Lösung folgen

https://magento.stackexchange.com/questions/272296/how-to-set-qty-to-product-on-msi-magento-2-3
Alam Zaib
quelle