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

Ответы:


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

Используйте менеджеров как можно больше. Держите ваши модули отделенными друг от друга.

Это Путь Магенто ™


setStockData - это то, что требуется. Нет необходимости вызывать -> setQuantityAndStockStatuses, хотя, похоже, это не вредит.
Роберт Эггинтон

9
Это прекрасно работает для одного продукта. Однако, когда вы читаете файл CSV с 5k SKU, производительность довольно плохая. У кого-то есть такая же проблема?
Медина

+1 за обновление вашего поста до версии magento 2.1.
ZFNerd

+1 за лучшие практики (и обновляющий ответ)
Акиф

Действительно ценю обновленный метод! 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);
}

как я могу использовать этот ответ для обновления магазина qty в magento 2?
Моджахед

@Mujahidh, вы можете попытаться передать scopeId в качестве второго параметра getStockItemBySku()метода
spiil

1
спасибо, кол-во обновляется, но не для магазина, поскольку оба магазина обновляют один и тот же кол-во.
Моджахед

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

Я боролся с этой же проблемой. Во время отладки я обнаружил, что данные о продукте имеют массив amount_and_stock_status, поэтому я попытался установить его с помощью:

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

и это начало работать для меня. Я по-прежнему устанавливаю $ product-> setStockData, если вы редактируете продукт и проверяете элемент в тех полях, в которых вы увидите оба поля: одно на вкладке "Общие", другое - в полях расширенного инвентаря. Я не до конца исследовал, почему их 2.


Сортировать и просто, очень хорошее решение !!! работает для меня +1
Мантан Дейв

Предпочтительное решение, так как это работает и требует меньше редактирования, чем другие +1
leedch

Когда продукт отключен, количество не обновляется; еще в состоянии включения работает должным образом. Можете ли вы помочь мне за это. Мой сайт в 2.1.9
Анил

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

Кстати, если вы посмотрите Сохранить ActionController на серверной части M2 использует фильтр для подготовки stock_data, вы можете найти этот фильтр в:

Magento \ Каталог \ Controller \ Adminhtml \ Продукт \ Initialization \ StockDataFilter


Я ценю ответ, но этот вариант не сработал. Спасибо за помощь.
Стивен Маленшек

0

Попробуйте это, при сохранении продукта в админке, они сохранили данные инвентаризации, используя событие 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 также предлагает функцию Multi Stock, поэтому для обновления на конкретном складе вы можете воспользоваться этим решением.

https://magento.stackexchange.com/questions/272296/how-to-set-qty-to-product-on-msi-magento-2-3
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.