BundleSelectionPrice.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Bundle\Pricing\Price;
  7. use Magento\Bundle\Model\Product\Price;
  8. use Magento\Catalog\Model\Product;
  9. use Magento\Catalog\Pricing\Price as CatalogPrice;
  10. use Magento\Framework\Event\ManagerInterface;
  11. use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
  12. use Magento\Framework\Pricing\Amount\AmountInterface;
  13. use Magento\Framework\Pricing\SaleableInterface;
  14. use Magento\Framework\Pricing\Price\AbstractPrice;
  15. /**
  16. * Bundle option price
  17. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  18. * @api
  19. * @since 100.0.2
  20. */
  21. class BundleSelectionPrice extends AbstractPrice
  22. {
  23. /**
  24. * Price model code
  25. */
  26. const PRICE_CODE = 'bundle_selection';
  27. /**
  28. * @var \Magento\Catalog\Model\Product
  29. */
  30. protected $bundleProduct;
  31. /**
  32. * Event manager
  33. *
  34. * @var \Magento\Framework\Event\ManagerInterface
  35. */
  36. protected $eventManager;
  37. /**
  38. * @var DiscountCalculator
  39. */
  40. protected $discountCalculator;
  41. /**
  42. * @var bool
  43. */
  44. protected $useRegularPrice;
  45. /**
  46. * @var Product
  47. */
  48. protected $selection;
  49. /**
  50. * Code of parent adjustment to be skipped from calculation
  51. *
  52. * @var string
  53. */
  54. protected $excludeAdjustment = null;
  55. /**
  56. * @param Product $saleableItem
  57. * @param float $quantity
  58. * @param CalculatorInterface $calculator
  59. * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
  60. * @param SaleableInterface $bundleProduct
  61. * @param ManagerInterface $eventManager
  62. * @param DiscountCalculator $discountCalculator
  63. * @param bool $useRegularPrice
  64. * @param array $excludeAdjustment
  65. */
  66. public function __construct(
  67. Product $saleableItem,
  68. $quantity,
  69. CalculatorInterface $calculator,
  70. \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
  71. SaleableInterface $bundleProduct,
  72. ManagerInterface $eventManager,
  73. DiscountCalculator $discountCalculator,
  74. $useRegularPrice = false,
  75. $excludeAdjustment = null
  76. ) {
  77. parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency);
  78. $this->bundleProduct = $bundleProduct;
  79. $this->eventManager = $eventManager;
  80. $this->discountCalculator = $discountCalculator;
  81. $this->useRegularPrice = $useRegularPrice;
  82. $this->selection = $saleableItem;
  83. $this->excludeAdjustment = $excludeAdjustment;
  84. }
  85. /**
  86. * Get the price value for one of selection product.
  87. *
  88. * @return bool|float
  89. */
  90. public function getValue()
  91. {
  92. if (null !== $this->value) {
  93. return $this->value;
  94. }
  95. $product = $this->selection;
  96. $bundleSelectionKey = 'bundle-selection-'
  97. . ($this->useRegularPrice ? 'regular-' : '')
  98. . 'value-'
  99. . $product->getSelectionId();
  100. if ($product->hasData($bundleSelectionKey)) {
  101. return $product->getData($bundleSelectionKey);
  102. }
  103. $priceCode = $this->useRegularPrice ? BundleRegularPrice::PRICE_CODE : FinalPrice::PRICE_CODE;
  104. if ($this->bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC) {
  105. // just return whatever the product's value is
  106. $value = $this->priceInfo
  107. ->getPrice($priceCode)
  108. ->getValue();
  109. } else {
  110. // don't multiply by quantity. Instead just keep as quantity = 1
  111. $selectionPriceValue = $this->selection->getSelectionPriceValue();
  112. if ($this->product->getSelectionPriceType()) {
  113. // calculate price for selection type percent
  114. $price = $this->bundleProduct->getPriceInfo()
  115. ->getPrice(CatalogPrice\RegularPrice::PRICE_CODE)
  116. ->getValue();
  117. $product = clone $this->bundleProduct;
  118. $product->setFinalPrice($price);
  119. $this->eventManager->dispatch(
  120. 'catalog_product_get_final_price',
  121. ['product' => $product, 'qty' => $this->bundleProduct->getQty()]
  122. );
  123. $price = $this->useRegularPrice ? $product->getData('price') : $product->getData('final_price');
  124. $value = $price * ($selectionPriceValue / 100);
  125. } else {
  126. // calculate price for selection type fixed
  127. $value = $this->priceCurrency->convert($selectionPriceValue);
  128. }
  129. }
  130. if (!$this->useRegularPrice) {
  131. $value = $this->discountCalculator->calculateDiscount($this->bundleProduct, $value);
  132. }
  133. $this->value = $this->priceCurrency->round($value);
  134. $product->setData($bundleSelectionKey, $this->value);
  135. return $this->value;
  136. }
  137. /**
  138. * Get Price Amount object
  139. *
  140. * @return AmountInterface
  141. */
  142. public function getAmount()
  143. {
  144. $product = $this->selection;
  145. $bundleSelectionKey = 'bundle-selection'
  146. . ($this->useRegularPrice ? 'regular-' : '')
  147. . '-amount-'
  148. . $product->getSelectionId();
  149. if ($product->hasData($bundleSelectionKey)) {
  150. return $product->getData($bundleSelectionKey);
  151. }
  152. $value = $this->getValue();
  153. if (!isset($this->amount[$value])) {
  154. $exclude = null;
  155. if ($this->getProduct()->getTypeId() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
  156. $exclude = $this->excludeAdjustment;
  157. }
  158. $this->amount[$value] = $this->calculator->getAmount(
  159. $value,
  160. $this->getProduct(),
  161. $exclude
  162. );
  163. $product->setData($bundleSelectionKey, $this->amount[$value]);
  164. }
  165. return $this->amount[$value];
  166. }
  167. /**
  168. * @return SaleableInterface
  169. */
  170. public function getProduct()
  171. {
  172. if ($this->bundleProduct->getPriceType() == Price::PRICE_TYPE_DYNAMIC) {
  173. return parent::getProduct();
  174. }
  175. return $this->bundleProduct;
  176. }
  177. }