Magento 2:プログラムでインベントリを更新する


12

次のコードでは、株式データを除外してすべての情報を保存できます。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";
}

1
これは役立つかもしれません:github.com/magento/magento2/issues/5771
Mukesh Chapagain

回答:


33

これは私にとってはうまくいきます:

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

編集

これは$product->save()Magento 2.1以降では非推奨であるため、これを処理する正しい方法ではなくなりました。これを行うには正しい方法で使用することですStockRegistryInterface

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

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

上記のコードでは、以下を使用できます。

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

できるだけマネージャを使用してください。モジュールを互いに切り離してください。

イッツザマジェントウェイ™


setStockDataが必要です。害はないようですが、-> setQuantityAndStockStatusesを呼び出す必要はありません。
Robert Egginton、2016年

9
1つの製品に最適です。ただし、5K SKUのCSVファイルを読み取る場合、パフォーマンスはかなり低下します。同じ問題を抱えている人はいますか?
メディナ2017

投稿をmagento 2.1バージョンに更新するための+1。
ZFNerd

ベストプラクティス(および回答の更新)の+1
Akif

更新されたメソッドを本当に感謝しています!あなたのようなコミュニティメンバーがこのような投稿を行っているため、Magentoは私たち全員にとって良くなっています!行く方法
JustinP

16

@ giel-berkersソリューションを使用している場合は、自動的に設定されないため、isInStockも設定する必要がある場合があります。したがって、次のコードは私にとって有用でした。

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);
}

この回答を使用して、magento 2で数量ストアを賢く更新するにはどうすればよいですか?
ムジャヒド

@Mujahidh scopeIdを2番目のパラメータとしてgetStockItemBySku()メソッドに渡そうとすることができます
spiil

1
おかげで、両方のストアが同じqtyを更新するため、qtyは更新されますが、ストアに関しては賢明ではありません。
ムジャヒド

8

他の答えが見逃したことの1つは、あなたがsetQty($qty)、あなたが提供する正確な値を適用する場合です。しかし、保存する直前にその製品のセールが行われた場合、元の数量は変更された可能性があります。だからあなたが本当にやりたいことは、数量に適用したい違いをMagentoに伝えることです。

幸い、Magento 2はこのための優れたメカニズムを提供します。見て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;
}

ここで、qty_correction値を設定すると、正確な量を適用するのではなく、差分を段階的に適用することがわかります。

したがって、より安全な数量保存の提案は次のとおりです。

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

7

私はこの同じ問題に苦労しました。デバッグ中に、製品データにquantity_and_stock_status配列があることがわかったので、次のように設定してみました。

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

そしてそれは私のために働き始めました。$ product-> setStockDataも設定していますが、商品を編集してフィールドの要素を調べると、両方が表示されます。1つは[全般]タブにあり、もう1つは詳細在庫フィールドにあります。2つある理由を完全に調査していません。


並べ替えとシンプルな、非常に良い解決策!私のために働く+1
Manthan Dave

これが機能し、他の方法よりも編集にかかる時間が少ないため、
推奨されるソリューション

製品が無効の場合、数量は更新されません。それ以外の場合は、有効ステータスが適切に機能しています。助けてくれませんか。私のサイトは2.1.9にあります
Anil

1

以下のコードは私が製品の数量を更新するのにうまく機能しています、

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();
    }
}

製品ステータスが無効の場合、私の場合、数量は更新されません。それを解決するのを手伝ってくれませんか。
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);

0

何よりもまずStoreIdを$ productに設定してみてください。

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

ところで、バックエンドでSave ActionControllerを見ると、M2はprepare stock_dataにフィルターを使用しています。そのフィルターは次の場所にあります。

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


回答には感謝しますが、そのオプションは機能しませんでした。助けてくれてありがとう。
Stephen Malenshek

0

管理者で製品を保存しているときにMagento_CatalogInventoryモジュールオブザーバーのイベントcatalog_product_save_afterを使用して在庫データを保存してみてください。

Magento \ CatalogInventory \ Observer \ SaveInventoryDataObserver


0

magento 2.0.9でも同じ問題が発生し、次のコードが私のケースで機能しています

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

0

Magento2にはマルチ在庫機能も用意されているため、特定の在庫ソースで更新するには、このソリューションに従うことができます

https://magento.stackexchange.com/questions/272296/how-to-set-qty-to-product-on-msi-magento-2-3
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.