StockManagement.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\CatalogInventory\Model;
  7. use Magento\CatalogInventory\Api\Data\StockItemInterface;
  8. use Magento\CatalogInventory\Api\RegisterProductSaleInterface;
  9. use Magento\CatalogInventory\Api\RevertProductSaleInterface;
  10. use Magento\CatalogInventory\Api\StockConfigurationInterface;
  11. use Magento\CatalogInventory\Api\StockManagementInterface;
  12. use Magento\CatalogInventory\Model\ResourceModel\QtyCounterInterface;
  13. use Magento\CatalogInventory\Model\Spi\StockRegistryProviderInterface;
  14. use Magento\Catalog\Api\ProductRepositoryInterface;
  15. use Magento\CatalogInventory\Model\ResourceModel\Stock as ResourceStock;
  16. /**
  17. * Implements a few interfaces for backward compatibility
  18. */
  19. class StockManagement implements StockManagementInterface, RegisterProductSaleInterface, RevertProductSaleInterface
  20. {
  21. /**
  22. * @var StockRegistryProviderInterface
  23. */
  24. protected $stockRegistryProvider;
  25. /**
  26. * @var StockState
  27. */
  28. protected $stockState;
  29. /**
  30. * @var StockConfigurationInterface
  31. */
  32. protected $stockConfiguration;
  33. /**
  34. * @var ProductRepositoryInterface
  35. */
  36. protected $productRepository;
  37. /**
  38. * @var ResourceStock
  39. */
  40. protected $resource;
  41. /**
  42. * @var QtyCounterInterface
  43. */
  44. private $qtyCounter;
  45. /**
  46. * @var StockRegistryStorage
  47. */
  48. private $stockRegistryStorage;
  49. /**
  50. * @param ResourceStock $stockResource
  51. * @param StockRegistryProviderInterface $stockRegistryProvider
  52. * @param StockState $stockState
  53. * @param StockConfigurationInterface $stockConfiguration
  54. * @param ProductRepositoryInterface $productRepository
  55. * @param QtyCounterInterface $qtyCounter
  56. * @param StockRegistryStorage|null $stockRegistryStorage
  57. */
  58. public function __construct(
  59. ResourceStock $stockResource,
  60. StockRegistryProviderInterface $stockRegistryProvider,
  61. StockState $stockState,
  62. StockConfigurationInterface $stockConfiguration,
  63. ProductRepositoryInterface $productRepository,
  64. QtyCounterInterface $qtyCounter,
  65. StockRegistryStorage $stockRegistryStorage = null
  66. ) {
  67. $this->stockRegistryProvider = $stockRegistryProvider;
  68. $this->stockState = $stockState;
  69. $this->stockConfiguration = $stockConfiguration;
  70. $this->productRepository = $productRepository;
  71. $this->qtyCounter = $qtyCounter;
  72. $this->resource = $stockResource;
  73. $this->stockRegistryStorage = $stockRegistryStorage ?: \Magento\Framework\App\ObjectManager::getInstance()
  74. ->get(StockRegistryStorage::class);
  75. }
  76. /**
  77. * Subtract product qtys from stock.
  78. *
  79. * Return array of items that require full save.
  80. *
  81. * @param string[] $items
  82. * @param int $websiteId
  83. * @return StockItemInterface[]
  84. * @throws \Magento\Framework\Exception\LocalizedException
  85. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  86. */
  87. public function registerProductsSale($items, $websiteId = null)
  88. {
  89. //if (!$websiteId) {
  90. $websiteId = $this->stockConfiguration->getDefaultScopeId();
  91. //}
  92. $this->getResource()->beginTransaction();
  93. $lockedItems = $this->getResource()->lockProductsStock(array_keys($items), $websiteId);
  94. $fullSaveItems = $registeredItems = [];
  95. foreach ($lockedItems as $lockedItemRecord) {
  96. $productId = $lockedItemRecord['product_id'];
  97. $this->stockRegistryStorage->removeStockItem($productId, $websiteId);
  98. /** @var StockItemInterface $stockItem */
  99. $orderedQty = $items[$productId];
  100. $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId);
  101. $stockItem->setQty($lockedItemRecord['qty']); // update data from locked item
  102. $canSubtractQty = $stockItem->getItemId() && $this->canSubtractQty($stockItem);
  103. if (!$canSubtractQty || !$this->stockConfiguration->isQty($lockedItemRecord['type_id'])) {
  104. continue;
  105. }
  106. if (!$stockItem->hasAdminArea()
  107. && !$this->stockState->checkQty($productId, $orderedQty, $stockItem->getWebsiteId())
  108. ) {
  109. $this->getResource()->commit();
  110. throw new \Magento\Framework\Exception\LocalizedException(
  111. __('Not all of your products are available in the requested quantity.')
  112. );
  113. }
  114. if ($this->canSubtractQty($stockItem)) {
  115. $stockItem->setQty($stockItem->getQty() - $orderedQty);
  116. }
  117. $registeredItems[$productId] = $orderedQty;
  118. if (!$this->stockState->verifyStock($productId, $stockItem->getWebsiteId())
  119. || $this->stockState->verifyNotification(
  120. $productId,
  121. $stockItem->getWebsiteId()
  122. )
  123. ) {
  124. $fullSaveItems[] = $stockItem;
  125. }
  126. }
  127. $this->qtyCounter->correctItemsQty($registeredItems, $websiteId, '-');
  128. $this->getResource()->commit();
  129. return $fullSaveItems;
  130. }
  131. /**
  132. * @inheritdoc
  133. */
  134. public function revertProductsSale($items, $websiteId = null)
  135. {
  136. //if (!$websiteId) {
  137. $websiteId = $this->stockConfiguration->getDefaultScopeId();
  138. //}
  139. $revertItems = [];
  140. foreach ($items as $productId => $qty) {
  141. $stockItem = $this->stockRegistryProvider->getStockItem($productId, $websiteId);
  142. $canSubtractQty = $stockItem->getItemId() && $this->canSubtractQty($stockItem);
  143. if (!$canSubtractQty || !$this->stockConfiguration->isQty($stockItem->getTypeId())) {
  144. continue;
  145. }
  146. $revertItems[$productId] = $qty;
  147. }
  148. $this->qtyCounter->correctItemsQty($revertItems, $websiteId, '+');
  149. return $revertItems;
  150. }
  151. /**
  152. * Get back to stock (when order is canceled or whatever else)
  153. *
  154. * @param int $productId
  155. * @param float $qty
  156. * @param int $scopeId
  157. * @return bool
  158. */
  159. public function backItemQty($productId, $qty, $scopeId = null)
  160. {
  161. //if (!$scopeId) {
  162. $scopeId = $this->stockConfiguration->getDefaultScopeId();
  163. //}
  164. $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId);
  165. if ($stockItem->getItemId() && $this->stockConfiguration->isQty($this->getProductType($productId))) {
  166. if ($this->canSubtractQty($stockItem)) {
  167. $stockItem->setQty($stockItem->getQty() + $qty);
  168. }
  169. if ($this->stockConfiguration->getCanBackInStock($stockItem->getStoreId()) && $stockItem->getQty()
  170. > $stockItem->getMinQty()
  171. ) {
  172. $stockItem->setIsInStock(true);
  173. $stockItem->setStockStatusChangedAutomaticallyFlag(true);
  174. }
  175. $stockItem->save();
  176. }
  177. return true;
  178. }
  179. /**
  180. * Get Product type
  181. *
  182. * @param int $productId
  183. * @return string
  184. */
  185. protected function getProductType($productId)
  186. {
  187. return $this->productRepository->getById($productId)->getTypeId();
  188. }
  189. /**
  190. * Get stock resource.
  191. *
  192. * @return ResourceStock
  193. */
  194. protected function getResource()
  195. {
  196. return $this->resource;
  197. }
  198. /**
  199. * Check if is possible subtract value from item qty
  200. *
  201. * @param StockItemInterface $stockItem
  202. * @return bool
  203. */
  204. protected function canSubtractQty(StockItemInterface $stockItem)
  205. {
  206. return $stockItem->getManageStock() && $this->stockConfiguration->canSubtractQty();
  207. }
  208. }