SuggestQtyPlugin.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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\Exception\LocalizedException;
  10. use Magento\InventoryCatalogApi\Model\GetSkusByProductIdsInterface;
  11. use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface;
  12. use Magento\InventorySalesApi\Api\Data\SalesChannelInterface;
  13. use Magento\InventorySalesApi\Api\GetProductSalableQtyInterface;
  14. use Magento\InventorySalesApi\Api\StockResolverInterface;
  15. use Magento\Store\Model\StoreManagerInterface;
  16. /**
  17. * Replace legacy suggest quantity
  18. */
  19. class SuggestQtyPlugin
  20. {
  21. /**
  22. * @var GetProductSalableQtyInterface
  23. */
  24. private $getProductSalableQty;
  25. /**
  26. * @var GetSkusByProductIdsInterface
  27. */
  28. private $getSkusByProductIds;
  29. /**
  30. * @var StockResolverInterface
  31. */
  32. private $stockResolver;
  33. /**
  34. * @var StoreManagerInterface
  35. */
  36. private $storeManager;
  37. /**
  38. * @var GetStockItemConfigurationInterface
  39. */
  40. private $getStockItemConfiguration;
  41. /**
  42. * @param GetProductSalableQtyInterface $getProductSalableQty
  43. * @param GetSkusByProductIdsInterface $getSkusByProductIds
  44. * @param StockResolverInterface $stockResolver
  45. * @param StoreManagerInterface $storeManager
  46. * @param GetStockItemConfigurationInterface $getStockItemConfiguration
  47. * @SuppressWarnings(PHPMD.LongVariable)
  48. */
  49. public function __construct(
  50. GetProductSalableQtyInterface $getProductSalableQty,
  51. GetSkusByProductIdsInterface $getSkusByProductIds,
  52. StockResolverInterface $stockResolver,
  53. StoreManagerInterface $storeManager,
  54. GetStockItemConfigurationInterface $getStockItemConfiguration
  55. ) {
  56. $this->getProductSalableQty = $getProductSalableQty;
  57. $this->getSkusByProductIds = $getSkusByProductIds;
  58. $this->stockResolver = $stockResolver;
  59. $this->storeManager = $storeManager;
  60. $this->getStockItemConfiguration = $getStockItemConfiguration;
  61. }
  62. /**
  63. * Replace legacy suggest quantity
  64. *
  65. * @param StockStateInterface $subject
  66. * @param \Closure $proceed
  67. * @param int $productId
  68. * @param float $qty
  69. * @param int|null $scopeId
  70. * @return float
  71. *
  72. * @return float
  73. * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  74. * @SuppressWarnings(PHPMD.LongVariable)
  75. */
  76. public function aroundSuggestQty(
  77. StockStateInterface $subject,
  78. \Closure $proceed,
  79. $productId,
  80. $qty,
  81. $scopeId = null
  82. ): float {
  83. try {
  84. $skus = $this->getSkusByProductIds->execute([$productId]);
  85. $productSku = $skus[$productId];
  86. $websiteCode = $this->storeManager->getWebsite()->getCode();
  87. $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode);
  88. $stockId = (int)$stock->getStockId();
  89. $stockItemConfiguration = $this->getStockItemConfiguration->execute($productSku, $stockId);
  90. $qtyIncrements = $stockItemConfiguration->getQtyIncrements();
  91. if ($qty <= 0 || $stockItemConfiguration->isManageStock() === false || $qtyIncrements < 2) {
  92. throw new LocalizedException(__('Wrong condition.'));
  93. }
  94. $minQty = max($stockItemConfiguration->getMinSaleQty(), $qtyIncrements);
  95. $divisibleMin = ceil($minQty / $qtyIncrements) * $qtyIncrements;
  96. $maxQty = min(
  97. $this->getProductSalableQty->execute($productSku, $stockId),
  98. $stockItemConfiguration->getMaxSaleQty()
  99. );
  100. $divisibleMax = floor($maxQty / $qtyIncrements) * $qtyIncrements;
  101. if ($qty < $minQty || $qty > $maxQty || $divisibleMin > $divisibleMax) {
  102. throw new LocalizedException(__('Wrong condition.'));
  103. }
  104. $closestDivisibleLeft = floor($qty / $qtyIncrements) * $qtyIncrements;
  105. $closestDivisibleRight = $closestDivisibleLeft + $qtyIncrements;
  106. $acceptableLeft = min(max($divisibleMin, $closestDivisibleLeft), $divisibleMax);
  107. $acceptableRight = max(min($divisibleMax, $closestDivisibleRight), $divisibleMin);
  108. return abs($acceptableLeft - $qty) < abs($acceptableRight - $qty) ? $acceptableLeft : $acceptableRight;
  109. } catch (LocalizedException $e) {
  110. return $qty;
  111. }
  112. }
  113. }