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
Мукеш Чапагейн

Ответы:

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);
}
spiil
источник
как я могу использовать этот ответ для обновления магазина 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
}
CYK
источник
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);
MHK Developer
источник
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

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

Попробуйте это, при сохранении продукта в админке, они сохранили данные инвентаризации, используя событие catalog_product_save_after в Magento_CatalogInventoryмодуле обозревателя

Magento \ CatalogInventory \ Observer \ SaveInventoryDataObserver

saravanavelu
источник
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
Алам Заиб
источник