Magento 2: Atualizando Programaticamente o Inventário

12

No código a seguir, sou capaz de armazenar todas as informações com a exclusão dos dados de estoque. Algo mudou no 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
fonte
11
Isso pode ajudar: github.com/magento/magento2/issues/5771
Mukesh Chapagain 10/10

Respostas:

33

Isso funciona para mim:

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

Editar :

Esta não é mais a maneira correta de lidar com isso, porque $product->save()está obsoleta desde o Magento 2.1. A maneira correta de fazer isso é usando o StockRegistryInterface:

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

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

Com o código acima, você pode usar o seguinte:

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

Use gerentes , tanto quanto possível. Mantenha seus módulos separados um do outro.

É o Magento Way ™

Giel Berkers
fonte
setStockData é o que é necessário. Não há necessidade de chamar -> setQuantityAndStockStatuses, embora pareça não causar nenhum dano.
9788 Robert Egginton #
9
Funciona muito bem para um produto. No entanto, ao ler um arquivo CSV com 5k SKUs, o desempenho é muito ruim. Alguém mais está tendo o mesmo problema?
medina
+1 para atualizar sua postagem para a versão magento 2.1.
ZFNerd
+1 para práticas recomendadas (e resposta de atualização)
Akif
Realmente aprecio o método atualizado! O Magento está melhorando para todos nós por causa de membros da comunidade como você fazendo posts como este! Caminho a percorrer
JustinP
16

Se você estiver usando a solução @ giel-berkers, talvez seja necessário definir o isInStock também, porque não será definido automaticamente. Portanto, o código a seguir foi útil para mim:

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
fonte
como posso usar esta resposta para atualizar a loja de quantidade no magento 2?
Mujahidh 22/03/19
@Mujahidh você pode tentar passar ScopeId como um segundo parâmetro para o getStockItemBySku()método
spiil
11
obrigado, qty está atualizando, mas não é sensato em termos de loja, pois as duas lojas atualizam o mesmo qty.
Mujahidh 25/03/19
8

Uma coisa que as outras respostas faltaram é que, se você setQty($qty)aplicar o valor exato que você fornecer. Porém, se uma venda foi feita para esse produto um momento antes da sua gravação, o qty original poderia ter sido alterado. Então, o que você realmente deseja fazer é dizer ao Magento a diferença que você deseja aplicar ao qty.

Felizmente, o Magento 2 fornece um bom mecanismo para isso. Dê uma olhada em 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;
}

Aqui vemos que, se você definir o qty_correctionvalor, ela aplicará a diferença gradualmente, em vez de aplicar uma quantia exata.

Portanto, minha sugestão para um salvamento de quantidade mais seguro é o seguinte:

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

Eu lutei com esse mesmo problema. Durante a depuração, descobri que os dados do produto têm uma matriz Quantity_and_stock_status, então tentei configurá-lo com:

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

e começou a trabalhar para mim. Ainda estou definindo o $ product-> setStockData também se você editar um produto e inspecionar o elemento nos campos, verá que ele possui os dois, um na guia geral e o outro nos campos avançados de inventário. Eu não investiguei completamente por que existem dois deles.

Kevin Chavez
fonte
tipo e simples, muito boa solução !!! trabalha para mim +1
Manthan Dave
Solução preferida, pois isso funciona e tem muito menos edição do que os outros +1
leedch
Quando o produto é Desativado, a quantidade não é atualizada; mais no status de habilitação funcionando corretamente. Você pode me ajudar? Meu site está em 2.1.9
Anil
1

O código abaixo está funcionando bem para atualizar a quantidade do produto,

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
fonte
Quando o status do produto é desativado, a quantidade não é atualizada no meu caso. Você pode me ajudar a resolvê-lo.
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);
Desenvolvedor MHK
fonte
0

Tente definir StoreId como $ product antes de tudo e talvez substitua:

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

BTW Se você olhar o Save ActionController no backend M2, usa um filtro para preparar stock_data, você pode encontrar esse filtro em:

Magento \ Catálogo \ Controlador \ Adminhtml \ Produto \ Inicialização \ StockDataFilter

MauroNigrele
fonte
Agradeço a resposta, mas essa opção não funcionou. Obrigado pela ajuda.
Stephen Malenshek
0

Tente isso, ao salvar o produto no administrador, eles salvaram os dados do inventário usando o evento catalog_product_save_after no Magento_CatalogInventorymódulo observador

Magento \ CatalogInventory \ Observer \ SaveInventoryDataObserver

saravanavelu
fonte
0

Eu tive o mesmo problema para o magento 2.0.9 e o código a seguir está funcionando no meu caso

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

O Magento2 também vem com o recurso de estoque múltiplo, para atualizar uma fonte de estoque específica, você pode seguir esta solução

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