stockRegistryProvider = $stockRegistryProvider; $this->stockState = $stockState; $this->stockConfiguration = $stockConfiguration; $this->productRepository = $productRepository; $this->qtyCounter = $qtyCounter; $this->resource = $stockResource; $this->stockRegistryStorage = $stockRegistryStorage ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(StockRegistryStorage::class); } /** * Subtract product qtys from stock. * * Return array of items that require full save. * * @param string[] $items * @param int $websiteId * @return StockItemInterface[] * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function registerProductsSale($items, $websiteId = null) { //if (!$websiteId) { $websiteId = $this->stockConfiguration->getDefaultScopeId(); //} $this->getResource()->beginTransaction(); $lockedItems = $this->getResource()->lockProductsStock(array_keys($items), $websiteId); $fullSaveItems = $registeredItems = []; foreach ($lockedItems as $lockedItemRecord) { $productId = $lockedItemRecord['product_id']; $this->stockRegistryStorage->removeStockItem($productId, $websiteId); /** @var StockItemInterface $stockItem */ $orderedQty = $items[$productId]; $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId); $stockItem->setQty($lockedItemRecord['qty']); // update data from locked item $canSubtractQty = $stockItem->getItemId() && $this->canSubtractQty($stockItem); if (!$canSubtractQty || !$this->stockConfiguration->isQty($lockedItemRecord['type_id'])) { continue; } if (!$stockItem->hasAdminArea() && !$this->stockState->checkQty($productId, $orderedQty, $stockItem->getWebsiteId()) ) { $this->getResource()->commit(); throw new \Magento\Framework\Exception\LocalizedException( __('Not all of your products are available in the requested quantity.') ); } if ($this->canSubtractQty($stockItem)) { $stockItem->setQty($stockItem->getQty() - $orderedQty); } $registeredItems[$productId] = $orderedQty; if (!$this->stockState->verifyStock($productId, $stockItem->getWebsiteId()) || $this->stockState->verifyNotification( $productId, $stockItem->getWebsiteId() ) ) { $fullSaveItems[] = $stockItem; } } $this->qtyCounter->correctItemsQty($registeredItems, $websiteId, '-'); $this->getResource()->commit(); return $fullSaveItems; } /** * @inheritdoc */ public function revertProductsSale($items, $websiteId = null) { //if (!$websiteId) { $websiteId = $this->stockConfiguration->getDefaultScopeId(); //} $revertItems = []; foreach ($items as $productId => $qty) { $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId); $canSubtractQty = $stockItem->getItemId() && $this->canSubtractQty($stockItem); if (!$canSubtractQty || !$this->stockConfiguration->isQty($stockItem->getTypeId())) { continue; } $revertItems[$productId] = $qty; } $this->qtyCounter->correctItemsQty($revertItems, $websiteId, '+'); return $revertItems; } /** * Get back to stock (when order is canceled or whatever else) * * @param int $productId * @param float $qty * @param int $scopeId * @return bool */ public function backItemQty($productId, $qty, $scopeId = null) { //if (!$scopeId) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); //} $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); if ($stockItem->getItemId() && $this->stockConfiguration->isQty($this->getProductType($productId))) { if ($this->canSubtractQty($stockItem)) { $stockItem->setQty($stockItem->getQty() + $qty); } if ($this->stockConfiguration->getCanBackInStock($stockItem->getStoreId()) && $stockItem->getQty() > $stockItem->getMinQty() ) { $stockItem->setIsInStock(true); $stockItem->setStockStatusChangedAutomaticallyFlag(true); } $stockItem->save(); } return true; } /** * Get Product type * * @param int $productId * @return string */ protected function getProductType($productId) { return $this->productRepository->getById($productId)->getTypeId(); } /** * Get stock resource. * * @return ResourceStock */ protected function getResource() { return $this->resource; } /** * Check if is possible subtract value from item qty * * @param StockItemInterface $stockItem * @return bool */ protected function canSubtractQty(StockItemInterface $stockItem) { return $stockItem->getManageStock() && $this->stockConfiguration->canSubtractQty(); } }