GiftWrapProcessor.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. /**
  3. * @copyright Vertex. All rights reserved. https://www.vertexinc.com/
  4. * @author Mediotype https://www.mediotype.com/
  5. */
  6. namespace Vertex\Tax\Model\Api\Data\InvoiceRequestBuilder;
  7. use Magento\Sales\Api\Data\OrderItemExtensionInterface;
  8. use Magento\Sales\Api\OrderRepositoryInterface;
  9. use Vertex\Data\LineItemInterface;
  10. use Vertex\Data\LineItemInterfaceFactory;
  11. use Vertex\Tax\Model\Config;
  12. use Vertex\Tax\Model\Repository\TaxClassNameRepository;
  13. /**
  14. * Processes GiftWrapping information for Invoices and Creditmemos
  15. */
  16. class GiftWrapProcessor
  17. {
  18. /** @var TaxClassNameRepository */
  19. private $classNameRepository;
  20. /** @var Config */
  21. private $config;
  22. /** @var LineItemInterfaceFactory */
  23. private $lineItemFactory;
  24. /** @var OrderRepositoryInterface */
  25. private $orderRepository;
  26. /**
  27. * @param OrderRepositoryInterface $orderRepository
  28. * @param Config $config
  29. * @param LineItemInterfaceFactory $lineItemFactory
  30. * @param TaxClassNameRepository $classNameRepository
  31. */
  32. public function __construct(
  33. OrderRepositoryInterface $orderRepository,
  34. Config $config,
  35. LineItemInterfaceFactory $lineItemFactory,
  36. TaxClassNameRepository $classNameRepository
  37. ) {
  38. $this->orderRepository = $orderRepository;
  39. $this->config = $config;
  40. $this->lineItemFactory = $lineItemFactory;
  41. $this->classNameRepository = $classNameRepository;
  42. }
  43. /**
  44. * Determine the items and amount (per item) being invoiced or credited for Giftwrapping
  45. *
  46. * Magento stores the item-level Giftwrapping on the Order Item, but does not do so
  47. * on the Invoice or Creditmemo item. Instead, the invoice or creditmemo contains the
  48. * total amount invoiced for items and somehow it is applied to the Order Item's amount
  49. * invoiced or credited.
  50. *
  51. * Since we use unique product codes for the item/giftwrap combination, we go through
  52. * this process to determine both the items we're invoicing giftwrap for, and the
  53. * amount of the total invoice for that item.
  54. *
  55. * That doesn't explain why we're using percentages though - and perhaps we don't need
  56. * to be. Percentages here fix a theoretical scenario where the $totalItemAmount
  57. * does not equal the sum of the item-level gift wrappings.
  58. *
  59. * @param int $orderId Order ID the invoice or creditmemo is for
  60. * @param int[] $includedOrderItemIds Order Item IDs of items on the invoice or creditmemo
  61. * @param float $totalItemAmount Total amount invoiced or credited for item-level Gift wrap
  62. * @return float[] array of amounts indexed by Order Item ID
  63. */
  64. public function getGiftWrapAmounts($orderId, $includedOrderItemIds, $totalItemAmount)
  65. {
  66. $order = $this->orderRepository->get($orderId);
  67. $totalAmount = 0;
  68. $orderItemAmounts = [];
  69. foreach ($order->getItems() as $orderItem) {
  70. if (!in_array($orderItem->getItemId(), $includedOrderItemIds, false)) {
  71. continue;
  72. }
  73. if ($orderItem->getExtensionAttributes() === null ||
  74. !$orderItem->getExtensionAttributes() instanceof OrderItemExtensionInterface) {
  75. continue;
  76. }
  77. $amount = (float)$orderItem->getExtensionAttributes()->getGwBasePrice();
  78. $totalAmount += $amount;
  79. $orderItemAmounts[$orderItem->getItemId()] = $amount;
  80. }
  81. if ($totalAmount == 0) {
  82. return [];
  83. }
  84. $resultAmounts = [];
  85. foreach ($orderItemAmounts as $orderItemId => $orderItemAmount) {
  86. $percentage = $orderItemAmount / $totalAmount;
  87. $resultAmount = $totalItemAmount * $percentage;
  88. if ($resultAmount == 0) {
  89. continue;
  90. }
  91. $resultAmounts[$orderItemId] = $resultAmount;
  92. }
  93. return $resultAmounts;
  94. }
  95. /**
  96. * Create a {@see LineItemInterface}
  97. *
  98. * @param float $giftWrapAmount
  99. * @param string $sku
  100. * @param string|null $scopeCode
  101. * @return LineItemInterface
  102. */
  103. public function buildItem($giftWrapAmount, $sku, $scopeCode = null)
  104. {
  105. $productClass = $this->classNameRepository->getById($this->config->getGiftWrappingItemClass($scopeCode));
  106. /** @var LineItemInterface $lineItem */
  107. $lineItem = $this->lineItemFactory->create();
  108. $lineItem->setProductCode($this->config->getGiftWrappingItemCodePrefix($scopeCode) . $sku);
  109. $lineItem->setProductClass($productClass);
  110. $lineItem->setQuantity(1);
  111. $lineItem->setUnitPrice($giftWrapAmount);
  112. $lineItem->setExtendedPrice($giftWrapAmount);
  113. return $lineItem;
  114. }
  115. /**
  116. * Create a {@see LineItemInterface} for an Order-level Printed Card
  117. *
  118. * @param float|null $basePrice The result of the basePrice getter from the extension attributes
  119. * @param string|null $scopeCode
  120. * @return LineItemInterface|null
  121. */
  122. public function processOrderGiftCard($basePrice = null, $scopeCode = null)
  123. {
  124. if ($basePrice === null || (float)$basePrice <= 0) {
  125. return null;
  126. }
  127. $productCode = $this->config->getPrintedGiftcardCode($scopeCode);
  128. $productClass = $this->classNameRepository->getById($this->config->getPrintedGiftcardClass($scopeCode));
  129. /** @var LineItemInterface $lineItem */
  130. $lineItem = $this->lineItemFactory->create();
  131. $lineItem->setProductCode($productCode);
  132. $lineItem->setProductClass($productClass);
  133. $lineItem->setQuantity(1);
  134. $lineItem->setUnitPrice((float)$basePrice);
  135. $lineItem->setExtendedPrice((float)$basePrice);
  136. return $lineItem;
  137. }
  138. /**
  139. * Create a {@see LineItemInterface} for an Order-level Gift Wrap
  140. *
  141. * @param float|null $basePrice The result of the basePrice getter from the extension attributes
  142. * @param string|null $scopeCode
  143. * @return LineItemInterface|null
  144. */
  145. public function processOrderGiftWrap($basePrice = null, $scopeCode = null)
  146. {
  147. if ($basePrice === null || (float)$basePrice <= 0) {
  148. return null;
  149. }
  150. $productCode = $this->config->getGiftWrappingOrderCode($scopeCode);
  151. $productClass = $this->classNameRepository->getById($this->config->getGiftWrappingOrderClass($scopeCode));
  152. /** @var LineItemInterface $lineItem */
  153. $lineItem = $this->lineItemFactory->create();
  154. $lineItem->setProductCode($productCode);
  155. $lineItem->setProductClass($productClass);
  156. $lineItem->setQuantity(1);
  157. $lineItem->setUnitPrice((float)$basePrice);
  158. $lineItem->setExtendedPrice((float)$basePrice);
  159. return $lineItem;
  160. }
  161. }