Shipping.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Sales\Model\Order\Creditmemo\Total;
  7. use Magento\Framework\Pricing\PriceCurrencyInterface;
  8. /**
  9. * Order creditmemo shipping total calculation model
  10. */
  11. class Shipping extends AbstractTotal
  12. {
  13. /**
  14. * @var PriceCurrencyInterface
  15. */
  16. protected $priceCurrency;
  17. /**
  18. * Tax config
  19. *
  20. * @var \Magento\Tax\Model\Config
  21. */
  22. private $taxConfig;
  23. /**
  24. * @param PriceCurrencyInterface $priceCurrency
  25. * @param array $data
  26. */
  27. public function __construct(
  28. PriceCurrencyInterface $priceCurrency,
  29. array $data = []
  30. ) {
  31. parent::__construct($data);
  32. $this->priceCurrency = $priceCurrency;
  33. }
  34. /**
  35. * Collects credit memo shipping totals.
  36. *
  37. * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo
  38. * @return $this
  39. * @throws \Magento\Framework\Exception\LocalizedException
  40. */
  41. public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
  42. {
  43. $order = $creditmemo->getOrder();
  44. // amounts without tax
  45. $orderShippingAmount = $order->getShippingAmount();
  46. $orderBaseShippingAmount = $order->getBaseShippingAmount();
  47. $allowedAmount = $orderShippingAmount - $order->getShippingRefunded();
  48. $baseAllowedAmount = $orderBaseShippingAmount - $order->getBaseShippingRefunded();
  49. // amounts including tax
  50. $orderShippingInclTax = $order->getShippingInclTax();
  51. $orderBaseShippingInclTax = $order->getBaseShippingInclTax();
  52. $allowedTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded();
  53. $allowedAmountInclTax = $allowedAmount + $allowedTaxAmount;
  54. $baseAllowedAmountInclTax = $orderBaseShippingInclTax
  55. - $order->getBaseShippingRefunded()
  56. - $order->getBaseShippingTaxRefunded();
  57. // Check if the desired shipping amount to refund was specified (from invoice or another source).
  58. if ($creditmemo->hasBaseShippingAmount()) {
  59. // For the conditional logic, we will either use amounts that always include tax -OR- never include tax.
  60. // The logic uses the 'base' currency to be consistent with what the user (admin) provided as input.
  61. $useAmountsWithTax = $this->isSuppliedShippingAmountInclTax($order);
  62. // Since the user (admin) supplied 'desiredAmount' it already has tax -OR- does not include tax
  63. $desiredAmount = $this->priceCurrency->round($creditmemo->getBaseShippingAmount());
  64. $maxAllowedAmount = ($useAmountsWithTax ? $baseAllowedAmountInclTax : $baseAllowedAmount);
  65. $originalTotalAmount = ($useAmountsWithTax ? $orderBaseShippingInclTax : $orderBaseShippingAmount);
  66. // Note: ($x < $y + 0.0001) means ($x <= $y) for floats
  67. if ($desiredAmount < $this->priceCurrency->round($maxAllowedAmount) + 0.0001) {
  68. // since the admin is returning less than the allowed amount, compute the ratio being returned
  69. $ratio = 0;
  70. if ($originalTotalAmount > 0) {
  71. $ratio = $desiredAmount / $originalTotalAmount;
  72. }
  73. // capture amounts without tax
  74. // Note: ($x > $y - 0.0001) means ($x >= $y) for floats
  75. if ($desiredAmount > $maxAllowedAmount - 0.0001) {
  76. $shippingAmount = $allowedAmount;
  77. $baseShippingAmount = $baseAllowedAmount;
  78. } else {
  79. $shippingAmount = $this->priceCurrency->round($orderShippingAmount * $ratio);
  80. $baseShippingAmount = $this->priceCurrency->round($orderBaseShippingAmount * $ratio);
  81. }
  82. $shippingInclTax = $this->priceCurrency->round($orderShippingInclTax * $ratio);
  83. $baseShippingInclTax = $this->priceCurrency->round($orderBaseShippingInclTax * $ratio);
  84. } else {
  85. $maxAllowedAmount = $order->getBaseCurrency()->format($maxAllowedAmount, null, false);
  86. throw new \Magento\Framework\Exception\LocalizedException(
  87. __('Maximum shipping amount allowed to refund is: %1', $maxAllowedAmount)
  88. );
  89. }
  90. } else {
  91. $shippingAmount = $allowedAmount;
  92. $baseShippingAmount = $baseAllowedAmount;
  93. $shippingInclTax = $this->priceCurrency->round($allowedAmountInclTax);
  94. $baseShippingInclTax = $this->priceCurrency->round($baseAllowedAmountInclTax);
  95. }
  96. $creditmemo->setShippingAmount($shippingAmount);
  97. $creditmemo->setBaseShippingAmount($baseShippingAmount);
  98. $creditmemo->setShippingInclTax($shippingInclTax);
  99. $creditmemo->setBaseShippingInclTax($baseShippingInclTax);
  100. $creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $shippingAmount);
  101. $creditmemo->setBaseGrandTotal($creditmemo->getBaseGrandTotal() + $baseShippingAmount);
  102. return $this;
  103. }
  104. /**
  105. * Returns whether the user specified a shipping amount that already includes tax
  106. *
  107. * @param \Magento\Sales\Model\Order $order
  108. * @return bool
  109. */
  110. private function isSuppliedShippingAmountInclTax($order)
  111. {
  112. // returns true if we are only displaying shipping including tax, otherwise returns false
  113. return $this->getTaxConfig()->displaySalesShippingInclTax($order->getStoreId());
  114. }
  115. /**
  116. * Get the Tax Config.
  117. *
  118. * @return \Magento\Tax\Model\Config
  119. *
  120. * @deprecated 100.1.0
  121. */
  122. private function getTaxConfig()
  123. {
  124. if ($this->taxConfig === null) {
  125. $this->taxConfig = \Magento\Framework\App\ObjectManager::getInstance()->get(
  126. \Magento\Tax\Model\Config::class
  127. );
  128. }
  129. return $this->taxConfig;
  130. }
  131. }