TaxManagement.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <?php
  2. /**
  3. *
  4. * Copyright © Magento, Inc. All rights reserved.
  5. * See COPYING.txt for license details.
  6. */
  7. namespace Magento\Tax\Model\Sales\Order;
  8. use Magento\Framework\Exception\NoSuchEntityException;
  9. use Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterfaceFactory as TaxDetailsDataObjectFactory;
  10. use Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface as AppliedTax;
  11. use Magento\Sales\Model\Order\Tax\Item;
  12. class TaxManagement implements \Magento\Tax\Api\OrderTaxManagementInterface
  13. {
  14. /**
  15. * @var \Magento\Sales\Model\ResourceModel\Order\Tax\ItemFactory
  16. */
  17. protected $orderItemTaxFactory;
  18. /**
  19. * @var \Magento\Sales\Model\OrderFactory
  20. */
  21. protected $orderFactory;
  22. /**
  23. * @var \Magento\Tax\Api\Data\OrderTaxDetailsInterfaceFactory
  24. */
  25. protected $orderTaxDetailsDataObjectFactory;
  26. /**
  27. * @var \Magento\Tax\Api\Data\OrderTaxDetailsItemInterfaceFactory
  28. */
  29. protected $itemDataObjectFactory;
  30. /**
  31. * @var TaxDetailsDataObjectFactory
  32. */
  33. protected $appliedTaxDataObjectFactory;
  34. /**
  35. * @param \Magento\Sales\Model\OrderFactory $orderFactory
  36. * @param \Magento\Sales\Model\ResourceModel\Order\Tax\ItemFactory $orderItemTaxFactory
  37. * @param \Magento\Tax\Api\Data\OrderTaxDetailsInterfaceFactory $orderTaxDetailsDataObjectFactory
  38. * @param \Magento\Tax\Api\Data\OrderTaxDetailsItemInterfaceFactory $itemDataObjectFactory
  39. * @param TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory
  40. */
  41. public function __construct(
  42. \Magento\Sales\Model\OrderFactory $orderFactory,
  43. \Magento\Sales\Model\ResourceModel\Order\Tax\ItemFactory $orderItemTaxFactory,
  44. \Magento\Tax\Api\Data\OrderTaxDetailsInterfaceFactory $orderTaxDetailsDataObjectFactory,
  45. \Magento\Tax\Api\Data\OrderTaxDetailsItemInterfaceFactory $itemDataObjectFactory,
  46. TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory
  47. ) {
  48. $this->orderFactory = $orderFactory;
  49. $this->orderItemTaxFactory = $orderItemTaxFactory;
  50. $this->orderTaxDetailsDataObjectFactory = $orderTaxDetailsDataObjectFactory;
  51. $this->itemDataObjectFactory = $itemDataObjectFactory;
  52. $this->appliedTaxDataObjectFactory = $appliedTaxDataObjectFactory;
  53. }
  54. /**
  55. * Convert applied tax from array to data object
  56. *
  57. * @param TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory
  58. * @param array $itemAppliedTax
  59. * @param AppliedTax $existingAppliedTax
  60. * @return AppliedTax
  61. */
  62. protected function convertToAppliedTaxDataObject(
  63. TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory,
  64. $itemAppliedTax,
  65. AppliedTax $existingAppliedTax = null
  66. ) {
  67. // if there is an existingAppliedTax, include its amount and baseAmount
  68. $amount = $baseAmount = 0;
  69. if ($existingAppliedTax !== null) {
  70. $amount = $existingAppliedTax->getAmount();
  71. $baseAmount = $existingAppliedTax->getBaseAmount();
  72. }
  73. return $appliedTaxDataObjectFactory->create()
  74. ->setCode($itemAppliedTax['code'])
  75. ->setTitle($itemAppliedTax['title'])
  76. ->setPercent($itemAppliedTax['tax_percent'])
  77. ->setAmount($itemAppliedTax['real_amount'] + $amount)
  78. ->setBaseAmount($itemAppliedTax['real_base_amount'] + $baseAmount);
  79. }
  80. /**
  81. * Aggregate item applied taxes to get order applied taxes
  82. *
  83. * @param TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory
  84. * @param \Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[] $items
  85. * @return AppliedTax[]
  86. */
  87. protected function aggregateAppliedTaxes(TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory, $items)
  88. {
  89. $orderAppliedTaxes = [];
  90. $orderAppliedTaxesData = [];
  91. foreach ($items as $item) {
  92. $itemAppliedTaxes = $item->getAppliedTaxes();
  93. foreach ($itemAppliedTaxes as $itemAppliedTax) {
  94. $code = $itemAppliedTax->getCode();
  95. if (!isset($orderAppliedTaxesData[$code])) {
  96. $orderAppliedTaxesData[$code] = [
  97. Tax::KEY_CODE => $code,
  98. Tax::KEY_TITLE => $itemAppliedTax->getTitle(),
  99. Tax::KEY_PERCENT => $itemAppliedTax->getPercent(),
  100. Tax::KEY_AMOUNT => $itemAppliedTax->getAmount(),
  101. Tax::KEY_BASE_AMOUNT => $itemAppliedTax->getBaseAmount(),
  102. ];
  103. } else {
  104. $orderAppliedTaxesData[$code][Tax::KEY_AMOUNT] += $itemAppliedTax->getAmount();
  105. $orderAppliedTaxesData[$code][Tax::KEY_BASE_AMOUNT] += $itemAppliedTax->getBaseAmount();
  106. }
  107. }
  108. }
  109. foreach ($orderAppliedTaxesData as $orderAppliedTaxData) {
  110. $orderAppliedTaxes[] = $appliedTaxDataObjectFactory->create()
  111. ->setCode($orderAppliedTaxData[Tax::KEY_CODE])
  112. ->setTitle($orderAppliedTaxData[Tax::KEY_TITLE])
  113. ->setPercent($orderAppliedTaxData[Tax::KEY_PERCENT])
  114. ->setAmount($orderAppliedTaxData[Tax::KEY_AMOUNT])
  115. ->setBaseAmount($orderAppliedTaxData[Tax::KEY_BASE_AMOUNT]);
  116. }
  117. return $orderAppliedTaxes;
  118. }
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function getOrderTaxDetails($orderId)
  123. {
  124. $order = $this->orderFactory->create()->load($orderId);
  125. if (!$order) {
  126. throw new NoSuchEntityException(
  127. __(
  128. 'No such entity with %fieldName = %fieldValue',
  129. ['fieldName' => 'orderId', 'fieldValue' => $orderId]
  130. )
  131. );
  132. }
  133. $orderItemAppliedTaxes = $this->orderItemTaxFactory->create()->getTaxItemsByOrderId($orderId);
  134. $itemsData = [];
  135. foreach ($orderItemAppliedTaxes as $itemAppliedTax) {
  136. $key = $itemId = $associatedItemId = null;
  137. //group applied taxes by item
  138. if (isset($itemAppliedTax['item_id'])) {
  139. //The taxable is a product
  140. //Note: the associatedItemId is null
  141. $itemId = $itemAppliedTax['item_id'];
  142. $key = $itemId;
  143. } elseif (isset($itemAppliedTax['associated_item_id'])) {
  144. //The taxable is associated with a product, e.g., weee, gift wrapping, etc.
  145. //Note: the itemId is null
  146. $associatedItemId = $itemAppliedTax['associated_item_id'];
  147. $key = $itemAppliedTax['taxable_item_type'] . $associatedItemId;
  148. } else {
  149. //The taxable is not associated with a product, e.g., shipping
  150. //Use item type as key. Both the itemId and associatedItemId are null
  151. $key = $itemAppliedTax['taxable_item_type'];
  152. }
  153. // create the itemsData entry
  154. if (!isset($itemsData[$key])) {
  155. $itemsData[$key] = [
  156. Item::KEY_TYPE => $itemAppliedTax['taxable_item_type'],
  157. Item::KEY_ITEM_ID => $itemId, // might be null
  158. Item::KEY_ASSOCIATED_ITEM_ID => $associatedItemId, // might be null
  159. ];
  160. }
  161. $current = null;
  162. if (isset($itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']])) {
  163. $current = $itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']];
  164. }
  165. $itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']] =
  166. $this->convertToAppliedTaxDataObject($this->appliedTaxDataObjectFactory, $itemAppliedTax, $current);
  167. }
  168. $items = [];
  169. foreach ($itemsData as $itemData) {
  170. $items[] = $this->itemDataObjectFactory->create()
  171. ->setType($itemData[Item::KEY_TYPE])
  172. ->setItemId($itemData[Item::KEY_ITEM_ID])
  173. ->setAssociatedItemId($itemData[Item::KEY_ASSOCIATED_ITEM_ID])
  174. ->setAppliedTaxes($itemData[Item::KEY_APPLIED_TAXES]);
  175. }
  176. $orderAppliedTaxesDOs = $this->aggregateAppliedTaxes($this->appliedTaxDataObjectFactory, $items);
  177. return $this->orderTaxDetailsDataObjectFactory->create()
  178. ->setItems($items)
  179. ->setAppliedTaxes($orderAppliedTaxesDOs);
  180. }
  181. }