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

Answers:


34

这对我有用:

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

尽可能使用管理员。保持模块彼此分离。

这是Magento Way™


setStockData是必需的。尽管看起来没有害处,但无需调用-> setQuantityAndStockStatuses。
罗伯特·艾金顿

9
它非常适合一种产品。但是,当您读取具有5k SKU的CSV文件时,性能会很差。有人遇到同样的问题吗?
麦地那

+1将您的信息更新为magento 2.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

@Mujahidh,您可以尝试将scopeId作为第二个参数传递给getStockItemBySku()方法
spiil

1
谢谢,数量正在更新但不是明智的,因为两个商店都更新了相同的数量。
Mujahidh

8

其他答案遗漏的一件事是,如果您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
Manthan Dave

首选的解决方案,因为这种方法
行之有效,而且

当产品禁用时,数量不会更新;否则处于启用状态即可正常工作。你能帮我吗 我的网站位于2.1.9
Anil,

2
$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);

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

如果产品状态为禁用,则我的情况下数量不会更新。你能帮我解决这个问题吗?
艾尼尔

0

尝试先将StoreId设置为$ product,然后替换:

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

顺便说一句,如果您在后端M2上查看Save ActionController,则使用过滤器来准备stock_data,您可以在以下位置找到该过滤器:

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


我感谢您的答复,但该选择无效。谢谢您的帮助。
Stephen Malenshek's

0

尝试此操作,将产品保存为admin时,他们使用模块查看器中的event catalog_product_save_after保存了库存数据Magento_CatalogInventory

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.