Flatrate.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\OfflineShipping\Model\Carrier;
  7. use Magento\OfflineShipping\Model\Carrier\Flatrate\ItemPriceCalculator;
  8. use Magento\Quote\Model\Quote\Address\RateRequest;
  9. use Magento\Shipping\Model\Carrier\AbstractCarrier;
  10. use Magento\Shipping\Model\Carrier\CarrierInterface;
  11. use Magento\Shipping\Model\Rate\Result;
  12. /**
  13. * Flat rate shipping model
  14. *
  15. * @api
  16. * @since 100.0.2
  17. */
  18. class Flatrate extends AbstractCarrier implements CarrierInterface
  19. {
  20. /**
  21. * @var string
  22. */
  23. protected $_code = 'flatrate';
  24. /**
  25. * @var bool
  26. */
  27. protected $_isFixed = true;
  28. /**
  29. * @var \Magento\Shipping\Model\Rate\ResultFactory
  30. */
  31. protected $_rateResultFactory;
  32. /**
  33. * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
  34. */
  35. protected $_rateMethodFactory;
  36. /**
  37. * @var ItemPriceCalculator
  38. */
  39. private $itemPriceCalculator;
  40. /**
  41. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  42. * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
  43. * @param \Psr\Log\LoggerInterface $logger
  44. * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
  45. * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
  46. * @param ItemPriceCalculator $itemPriceCalculator
  47. * @param array $data
  48. */
  49. public function __construct(
  50. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  51. \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
  52. \Psr\Log\LoggerInterface $logger,
  53. \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
  54. \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
  55. \Magento\OfflineShipping\Model\Carrier\Flatrate\ItemPriceCalculator $itemPriceCalculator,
  56. array $data = []
  57. ) {
  58. $this->_rateResultFactory = $rateResultFactory;
  59. $this->_rateMethodFactory = $rateMethodFactory;
  60. $this->itemPriceCalculator = $itemPriceCalculator;
  61. parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
  62. }
  63. /**
  64. * @param RateRequest $request
  65. * @return Result|bool
  66. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  67. * @SuppressWarnings(PHPMD.NPathComplexity)
  68. */
  69. public function collectRates(RateRequest $request)
  70. {
  71. if (!$this->getConfigFlag('active')) {
  72. return false;
  73. }
  74. $freeBoxes = $this->getFreeBoxesCount($request);
  75. $this->setFreeBoxes($freeBoxes);
  76. /** @var Result $result */
  77. $result = $this->_rateResultFactory->create();
  78. $shippingPrice = $this->getShippingPrice($request, $freeBoxes);
  79. if ($shippingPrice !== false) {
  80. $method = $this->createResultMethod($shippingPrice);
  81. $result->append($method);
  82. }
  83. return $result;
  84. }
  85. /**
  86. * @param RateRequest $request
  87. * @return int
  88. */
  89. private function getFreeBoxesCount(RateRequest $request)
  90. {
  91. $freeBoxes = 0;
  92. if ($request->getAllItems()) {
  93. foreach ($request->getAllItems() as $item) {
  94. if ($item->getProduct()->isVirtual() || $item->getParentItem()) {
  95. continue;
  96. }
  97. if ($item->getHasChildren() && $item->isShipSeparately()) {
  98. $freeBoxes += $this->getFreeBoxesCountFromChildren($item);
  99. } elseif ($item->getFreeShipping()) {
  100. $freeBoxes += $item->getQty();
  101. }
  102. }
  103. }
  104. return $freeBoxes;
  105. }
  106. /**
  107. * @return array
  108. */
  109. public function getAllowedMethods()
  110. {
  111. return ['flatrate' => $this->getConfigData('name')];
  112. }
  113. /**
  114. * @param RateRequest $request
  115. * @param int $freeBoxes
  116. * @return bool|float
  117. */
  118. private function getShippingPrice(RateRequest $request, $freeBoxes)
  119. {
  120. $shippingPrice = false;
  121. $configPrice = $this->getConfigData('price');
  122. if ($this->getConfigData('type') === 'O') {
  123. // per order
  124. $shippingPrice = $this->itemPriceCalculator->getShippingPricePerOrder($request, $configPrice, $freeBoxes);
  125. } elseif ($this->getConfigData('type') === 'I') {
  126. // per item
  127. $shippingPrice = $this->itemPriceCalculator->getShippingPricePerItem($request, $configPrice, $freeBoxes);
  128. }
  129. $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice);
  130. if ($shippingPrice !== false && $request->getPackageQty() == $freeBoxes) {
  131. $shippingPrice = '0.00';
  132. }
  133. return $shippingPrice;
  134. }
  135. /**
  136. * @param int|float $shippingPrice
  137. * @return \Magento\Quote\Model\Quote\Address\RateResult\Method
  138. */
  139. private function createResultMethod($shippingPrice)
  140. {
  141. /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
  142. $method = $this->_rateMethodFactory->create();
  143. $method->setCarrier('flatrate');
  144. $method->setCarrierTitle($this->getConfigData('title'));
  145. $method->setMethod('flatrate');
  146. $method->setMethodTitle($this->getConfigData('name'));
  147. $method->setPrice($shippingPrice);
  148. $method->setCost($shippingPrice);
  149. return $method;
  150. }
  151. /**
  152. * @param mixed $item
  153. * @return mixed
  154. */
  155. private function getFreeBoxesCountFromChildren($item)
  156. {
  157. $freeBoxes = 0;
  158. foreach ($item->getChildren() as $child) {
  159. if ($child->getFreeShipping() && !$child->getProduct()->isVirtual()) {
  160. $freeBoxes += $item->getQty() * $child->getQty();
  161. }
  162. }
  163. return $freeBoxes;
  164. }
  165. }