CheckQuoteItemQtyPlugin.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\InventorySales\Plugin\StockState;
  8. use Magento\CatalogInventory\Api\StockStateInterface;
  9. use Magento\Framework\DataObject;
  10. use Magento\Framework\DataObject\Factory as ObjectFactory;
  11. use Magento\Framework\Exception\LocalizedException;
  12. use Magento\Framework\Exception\NoSuchEntityException;
  13. use Magento\Framework\Locale\FormatInterface;
  14. use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface;
  15. use Magento\InventorySales\Model\IsProductSalableCondition\BackOrderNotifyCustomerCondition;
  16. use Magento\InventorySales\Model\IsProductSalableForRequestedQtyCondition\ProductSalabilityError;
  17. use Magento\InventorySalesApi\Api\Data\SalesChannelInterface;
  18. use Magento\InventorySalesApi\Api\IsProductSalableForRequestedQtyInterface;
  19. use Magento\InventorySalesApi\Api\StockResolverInterface;
  20. use Magento\Store\Model\StoreManagerInterface;
  21. /**
  22. * Replace legacy quote item check
  23. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  24. */
  25. class CheckQuoteItemQtyPlugin
  26. {
  27. /**
  28. * @var ObjectFactory
  29. */
  30. private $objectFactory;
  31. /**
  32. * @var FormatInterface
  33. */
  34. private $format;
  35. /**
  36. * @var IsProductSalableForRequestedQtyInterface
  37. */
  38. private $isProductSalableForRequestedQty;
  39. /**
  40. * @var GetSkusByProductIdsInterface
  41. */
  42. private $getSkusByProductIds;
  43. /**
  44. * @var StockResolverInterface
  45. */
  46. private $stockResolver;
  47. /**
  48. * @var StoreManagerInterface
  49. */
  50. private $storeManager;
  51. /**
  52. * @var BackOrderNotifyCustomerCondition
  53. */
  54. private $backOrderNotifyCustomerCondition;
  55. /**
  56. * @param ObjectFactory $objectFactory
  57. * @param FormatInterface $format
  58. * @param IsProductSalableForRequestedQtyInterface $isProductSalableForRequestedQty
  59. * @param GetSkusByProductIdsInterface $getSkusByProductIds
  60. * @param StockResolverInterface $stockResolver
  61. * @param StoreManagerInterface $storeManager
  62. * @param BackOrderNotifyCustomerCondition $backOrderNotifyCustomerCondition
  63. * @SuppressWarnings(PHPMD.LongVariable)
  64. */
  65. public function __construct(
  66. ObjectFactory $objectFactory,
  67. FormatInterface $format,
  68. IsProductSalableForRequestedQtyInterface $isProductSalableForRequestedQty,
  69. GetSkusByProductIdsInterface $getSkusByProductIds,
  70. StockResolverInterface $stockResolver,
  71. StoreManagerInterface $storeManager,
  72. BackOrderNotifyCustomerCondition $backOrderNotifyCustomerCondition
  73. ) {
  74. $this->objectFactory = $objectFactory;
  75. $this->format = $format;
  76. $this->isProductSalableForRequestedQty = $isProductSalableForRequestedQty;
  77. $this->getSkusByProductIds = $getSkusByProductIds;
  78. $this->stockResolver = $stockResolver;
  79. $this->storeManager = $storeManager;
  80. $this->backOrderNotifyCustomerCondition = $backOrderNotifyCustomerCondition;
  81. }
  82. /**
  83. * Replace legacy quote item check
  84. *
  85. * @param StockStateInterface $subject
  86. * @param \Closure $proceed
  87. * @param int $productId
  88. * @param float $itemQty
  89. * @param float $qtyToCheck
  90. * @param float $origQty
  91. * @param int|null $scopeId
  92. *
  93. * @return DataObject
  94. * @throws LocalizedException
  95. * @throws NoSuchEntityException
  96. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  97. */
  98. public function aroundCheckQuoteItemQty(
  99. StockStateInterface $subject,
  100. \Closure $proceed,
  101. $productId,
  102. $itemQty,
  103. $qtyToCheck,
  104. $origQty,
  105. $scopeId = null
  106. ) {
  107. $result = $this->objectFactory->create();
  108. $result->setHasError(false);
  109. $qty = $this->getNumber($itemQty);
  110. $skus = $this->getSkusByProductIds->execute([$productId]);
  111. $productSku = $skus[$productId];
  112. $websiteCode = $this->storeManager->getWebsite()->getCode();
  113. $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode);
  114. $stockId = $stock->getStockId();
  115. $isSalableResult = $this->isProductSalableForRequestedQty->execute($productSku, (int)$stockId, $qty);
  116. if ($isSalableResult->isSalable() === false) {
  117. /** @var ProductSalabilityError $error */
  118. foreach ($isSalableResult->getErrors() as $error) {
  119. $result->setHasError(true)->setMessage($error->getMessage())->setQuoteMessage($error->getMessage())
  120. ->setQuoteMessageIndex('qty');
  121. }
  122. }
  123. $productSalableResult = $this->backOrderNotifyCustomerCondition->execute($productSku, (int)$stockId, $qty);
  124. if ($productSalableResult->getErrors()) {
  125. /** @var ProductSalabilityError $error */
  126. foreach ($productSalableResult->getErrors() as $error) {
  127. $result->setMessage($error->getMessage());
  128. }
  129. }
  130. return $result;
  131. }
  132. /**
  133. * Convert quantity to a valid float
  134. *
  135. * @param string|float|int|null $qty
  136. *
  137. * @return float|null
  138. */
  139. private function getNumber($qty)
  140. {
  141. if (!is_numeric($qty)) {
  142. return $this->format->getNumber($qty);
  143. }
  144. return $qty;
  145. }
  146. }