Magento 2: Memperbarui Persediaan secara Programatis

12

Dalam kode berikut, saya bisa menyimpan semua informasi dengan mengesampingkan data stok. Apakah ada yang berubah di Magento 2?

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
sumber
1
Ini mungkin membantu: github.com/magento/magento2/issues/5771
Mukesh Chapagain

Jawaban:

33

Ini bekerja untuk saya:

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

Edit :

Ini bukan lagi cara yang benar untuk menangani ini, karena $product->save()sudah usang sejak Magento 2.1. Cara yang benar untuk melakukan ini adalah dengan menggunakan StockRegistryInterface:

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

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

Dengan kode di atas, Anda dapat menggunakan yang berikut:

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

Gunakan Manajer sebanyak mungkin. Biarkan modul Anda dipisahkan satu sama lain.

Ini The Magento Way ™

Giel Berkers
sumber
setStockData adalah apa yang diperlukan. Tidak perlu memanggil -> setQuantityAndStockStatuses, meskipun tampaknya tidak ada salahnya.
Robert Egginton
9
Ini bekerja dengan baik untuk satu produk. Namun, ketika Anda membaca file CSV dengan 5k SKU kinerjanya sangat buruk. Adakah yang memiliki masalah yang sama?
medina
+1 untuk memperbarui posting Anda ke versi Magento 2.1.
ZFNerd
+1 untuk praktik terbaik (dan memperbarui jawaban)
Akif
Sangat menghargai Metode yang Diperbarui! Magento menjadi lebih baik bagi kita semua karena anggota komunitas seperti Anda melakukan posting seperti ini! Way to go
JustinP
16

Jika Anda menggunakan solusi @ giel-berkers, Anda mungkin perlu mengatur isInStock juga, karena itu tidak akan ditetapkan secara otomatis. Jadi, kode berikut bermanfaat bagi saya:

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
sumber
bagaimana saya bisa menggunakan jawaban ini untuk memperbarui qty store di magento 2?
Mujahidh
@ Mujahidh Anda dapat mencoba untuk melewatkan scopeId sebagai parameter kedua ke getStockItemBySku()metode
spiil
1
terima kasih, qty memperbarui tetapi tidak menyimpan bijaksana, untuk kedua toko memperbarui jumlah yang sama.
Mujahidh
8

Satu hal yang terlewatkan oleh jawaban lain adalah jika Anda setQty($qty), itu akan menerapkan nilai persis yang Anda berikan. Tetapi jika penjualan dilakukan untuk produk itu sesaat sebelum penyimpanan Anda, jumlah asli mungkin bisa berubah. Jadi yang ingin Anda lakukan adalah memberi tahu Magento perbedaan yang ingin Anda terapkan pada qty.

Untungnya, Magento 2 menyediakan mekanisme yang bagus untuk ini. Lihatlah 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;
}

Di sini kita melihat bahwa jika Anda menetapkan qty_correctionnilai, itu akan menerapkan perbedaan secara bertahap alih-alih menerapkan jumlah yang tepat.

Jadi saran saya untuk menghemat qty lebih aman adalah ini:

/**
 * @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
sumber
7

Saya berjuang dengan masalah yang sama ini. Saat debugging saya menemukan bahwa data produk memiliki array kuantitas_and_stock_status, jadi saya mencoba mengaturnya dengan:

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

dan itu mulai bekerja untuk saya. Saya masih menyetel $ product-> setStockData juga jika Anda mengedit produk dan memeriksa elemen pada bidang yang Anda akan melihat keduanya, satu ada di tab umum, yang lain di bidang inventaris canggih. Saya belum sepenuhnya menyelidiki mengapa ada 2 di antaranya.

Kevin Chavez
sumber
sortir dan sederhana, solusi yang sangat bagus !!! berfungsi untuk saya +1
Manthan Dave
Solusi yang dipilih, karena ini berfungsi dan membutuhkan pengeditan jauh lebih sedikit daripada yang lain +1
leedch
Ketika produk Nonaktifkan maka kuantitas tidak diperbarui; lain dalam mengaktifkan status berfungsi dengan benar. Bisakah Anda membantu saya untuk itu? Situs saya ada di 2.1.9
Anil
1

Kode di bawah ini berfungsi dengan baik bagi saya untuk memperbarui jumlah produk,

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
sumber
Ketika status produk dinonaktifkan maka kuantitas tidak diperbarui dalam kasus saya. Dapatkah Anda membantu saya menyelesaikannya?
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);
Pengembang MHK
sumber
0

Coba atur StoreId ke $ produk sebelumnya, dan mungkin ganti:

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

BTW Jika Anda melihat Simpan ActionController di backend M2 menggunakan filter untuk mempersiapkan stock_data Anda bisa menemukan filter itu di:

Magento \ Catalog \ Controller \ Adminhtml \ Product \ Inisialisasi \ StockDataFilter

MauroNigrele
sumber
Saya menghargai responsnya, tetapi opsi itu tidak berhasil. Terima kasih untuk bantuannya.
Stephen Malenshek
0

Coba ini, saat menyimpan produk di admin, mereka menyimpan data inventaris dengan menggunakan catalog_product_save_after acara di Magento_CatalogInventorypengamat modul

Magento \ CatalogInventory \ Observer \ SaveInventoryDataObserver

saravanavelu
sumber
0

Saya memiliki masalah yang sama untuk magento 2.0.9 dan kode berikut berfungsi dalam kasus saya

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

Magento2 juga hadir dengan fitur multi stok sehingga untuk memperbarui pada sumber stok tertentu Anda dapat mengikuti solusi ini

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