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