Magento 2: Actualización de inventario mediante programación


12

En el siguiente código, puedo almacenar toda la información con la exclusión de los datos de stock. ¿Ha cambiado algo en 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";
}

Respuestas:


33

Esto funciona para mi:

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

Editar :

Esta ya no es la forma correcta de manejar esto, porque $product->save()está en desuso desde Magento 2.1. La forma correcta de hacer esto es mediante el uso de StockRegistryInterface:

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

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

Con el código anterior, puede usar lo siguiente:

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

Use los gerentes tanto como sea posible. Mantenga sus módulos desacoplados entre sí.

Es el camino de Magento ™


setStockData es lo que se requiere. No hay necesidad de llamar -> setQuantityAndStockStatuses, aunque parece no hacer daño.
Robert Egginton

99
Funciona muy bien para un producto. Sin embargo, cuando lee un archivo CSV con 5k SKU, el rendimiento es bastante malo. ¿Alguien tiene el mismo problema?
medina

+1 para actualizar su publicación a la versión 2.1 de magento.
ZFNerd

+1 para mejores prácticas (y actualización de respuesta)
Akif

Realmente aprecio el método actualizado! ¡Magento está mejorando para todos nosotros debido a que miembros de la comunidad como tú hacen publicaciones como esta! Así se hace
JustinP

16

Si está utilizando la solución @ giel-berkers, es posible que también deba configurar isInStock, ya que no se configurará automáticamente. Entonces, el siguiente código fue útil para mí:

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

¿Cómo puedo usar esta respuesta para actualizar Qty Store Wise en Magento 2?
Mujahidh

@Mujahidh se puede tratar de pasar ScopeId como segundo parámetro al getStockItemBySku()método
spiil

1
gracias, qty se está actualizando, pero no es una tienda inteligente, ya que ambas tiendas actualizan la misma cantidad.
Mujahidh

8

Una cosa que las otras respuestas perdieron es que si usted setQty($qty)aplicará el valor exacto que proporcione. Pero si se realizó una venta para ese producto un momento antes de su ahorro, la cantidad original podría haber cambiado. Entonces, lo que realmente quiere hacer es decirle a Magento la diferencia que desea aplicar a la cantidad.

Afortunadamente, Magento 2 proporciona un buen mecanismo para esto. Echa un vistazo a 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;
}

Aquí vemos que si establece el qty_correctionvalor, aplicará la diferencia de forma incremental en lugar de aplicar una cantidad exacta.

Entonces, mi sugerencia para un ahorro de cantidad más seguro es esta:

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

Luché con este mismo problema. Durante la depuración descubrí que los datos del producto tienen una matriz cantidad_y_stock_estado, así que intenté configurarlo con:

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

y comenzó a funcionar para mí Todavía estoy configurando $ product-> setStockData también si editas un producto e inspeccionas el elemento en los campos, verás que tiene ambos, uno está en la pestaña general y el otro en los campos de inventario avanzado. No he investigado completamente por qué hay 2 de ellos.


tipo y simple, muy buena solución !!! funciona para mí +1
Manthan Dave

Solución preferida, ya que esto funciona y requiere mucho menos edición que las otras +1
leedch

Cuando el producto está desactivado, la cantidad no se actualiza; más en estado habilitado funciona correctamente. ¿Me pueden ayudar? Mi sitio está en 2.1.9
Anil

1

El siguiente código funciona bien para mí para actualizar la cantidad de productos,

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

Cuando el estado del producto está desactivado, la cantidad no se actualiza en mi caso. ¿Me pueden ayudar a resolverlo?
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

Intente configurar StoreId en $ product antes de todo, y tal vez reemplace:

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

Por cierto, si mira el Save ActionController en el backend, M2 usa un filtro para preparar stock_data, puede encontrar ese filtro en:

Magento \ Catálogo \ Controlador \ Adminhtml \ Producto \ Inicialización \ StockDataFilter


Agradezco la respuesta, pero esa opción no funcionó. Gracias por la ayuda.
Stephen Malenshek

0

Intente esto, al guardar el producto en admin, guardaron los datos de inventario mediante el evento catalog_product_save_after en el Magento_CatalogInventorymódulo observador

Magento \ CatalogInventory \ Observer \ SaveInventoryDataObserver


0

Tuve el mismo problema para magento 2.0.9 y el siguiente código funciona en mi caso

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

0

Magento2 también viene con la función Multi stock, por lo que para actualizar una fuente de stock en particular puede seguir esta solución

https://magento.stackexchange.com/questions/272296/how-to-set-qty-to-product-on-msi-magento-2-3
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.