Skip to content

Commit 4af33e7

Browse files
committed
Merge remote-tracking branch 'origin/MAGETWO-85998' into 2.3-develop-pr12
2 parents 8b75bf2 + c21609f commit 4af33e7

File tree

7 files changed

+372
-109
lines changed

7 files changed

+372
-109
lines changed

app/code/Magento/Sales/Model/Order/CreditmemoFactory.php

Lines changed: 128 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
*/
66
namespace Magento\Sales\Model\Order;
77

8+
use Magento\Bundle\Ui\DataProvider\Product\Listing\Collector\BundlePrice;
9+
use Magento\Sales\Api\Data\OrderItemInterface;
10+
811
/**
912
* Factory class for @see \Magento\Sales\Model\Order\Creditmemo
1013
*/
1114
class CreditmemoFactory
1215
{
1316
/**
14-
* Quote convert object
17+
* Order convert object.
1518
*
1619
* @var \Magento\Sales\Model\Convert\Order
1720
*/
@@ -63,31 +66,15 @@ public function createByOrder(\Magento\Sales\Model\Order $order, array $data = [
6366
{
6467
$totalQty = 0;
6568
$creditmemo = $this->convertor->toCreditmemo($order);
66-
$qtys = isset($data['qtys']) ? $data['qtys'] : [];
69+
$qtyList = isset($data['qtys']) ? $data['qtys'] : [];
6770

6871
foreach ($order->getAllItems() as $orderItem) {
69-
if (!$this->canRefundItem($orderItem, $qtys)) {
72+
if (!$this->canRefundItem($orderItem, $qtyList)) {
7073
continue;
7174
}
7275

7376
$item = $this->convertor->itemToCreditmemoItem($orderItem);
74-
if ($orderItem->isDummy()) {
75-
if (isset($data['qtys'][$orderItem->getParentItemId()])) {
76-
$parentQty = $data['qtys'][$orderItem->getParentItemId()];
77-
} else {
78-
$parentQty = $orderItem->getParentItem() ? $orderItem->getParentItem()->getQtyToRefund() : 1;
79-
}
80-
$qty = $this->calculateProductOptions($orderItem, $parentQty);
81-
$orderItem->setLockedDoShip(true);
82-
} else {
83-
if (isset($qtys[$orderItem->getId()])) {
84-
$qty = (double)$qtys[$orderItem->getId()];
85-
} elseif (!count($qtys)) {
86-
$qty = $orderItem->getQtyToRefund();
87-
} else {
88-
continue;
89-
}
90-
}
77+
$qty = $this->getQtyToRefund($orderItem, $qtyList);
9178
$totalQty += $qty;
9279
$item->setQty($qty);
9380
$creditmemo->addItem($item);
@@ -106,88 +93,39 @@ public function createByOrder(\Magento\Sales\Model\Order $order, array $data = [
10693
* @param \Magento\Sales\Model\Order\Invoice $invoice
10794
* @param array $data
10895
* @return Creditmemo
109-
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
110-
* @SuppressWarnings(PHPMD.NPathComplexity)
11196
*/
11297
public function createByInvoice(\Magento\Sales\Model\Order\Invoice $invoice, array $data = [])
11398
{
11499
$order = $invoice->getOrder();
115100
$totalQty = 0;
116-
$qtys = isset($data['qtys']) ? $data['qtys'] : [];
101+
$qtyList = isset($data['qtys']) ? $data['qtys'] : [];
117102
$creditmemo = $this->convertor->toCreditmemo($order);
118103
$creditmemo->setInvoice($invoice);
119104

120-
$invoiceQtysRefunded = [];
121-
foreach ($invoice->getOrder()->getCreditmemosCollection() as $createdCreditmemo) {
122-
if ($createdCreditmemo->getState() != Creditmemo::STATE_CANCELED &&
123-
$createdCreditmemo->getInvoiceId() == $invoice->getId()
124-
) {
125-
foreach ($createdCreditmemo->getAllItems() as $createdCreditmemoItem) {
126-
$orderItemId = $createdCreditmemoItem->getOrderItem()->getId();
127-
if (isset($invoiceQtysRefunded[$orderItemId])) {
128-
$invoiceQtysRefunded[$orderItemId] += $createdCreditmemoItem->getQty();
129-
} else {
130-
$invoiceQtysRefunded[$orderItemId] = $createdCreditmemoItem->getQty();
131-
}
132-
}
133-
}
134-
}
135-
136-
$invoiceQtysRefundLimits = [];
137-
foreach ($invoice->getAllItems() as $invoiceItem) {
138-
$invoiceQtyCanBeRefunded = $invoiceItem->getQty();
139-
$orderItemId = $invoiceItem->getOrderItem()->getId();
140-
if (isset($invoiceQtysRefunded[$orderItemId])) {
141-
$invoiceQtyCanBeRefunded = $invoiceQtyCanBeRefunded - $invoiceQtysRefunded[$orderItemId];
142-
}
143-
$invoiceQtysRefundLimits[$orderItemId] = $invoiceQtyCanBeRefunded;
144-
}
105+
$invoiceRefundLimitsQtyList = $this->getInvoiceRefundLimitsQtyList($invoice);
145106

146107
foreach ($invoice->getAllItems() as $invoiceItem) {
108+
/** @var OrderItemInterface $orderItem */
147109
$orderItem = $invoiceItem->getOrderItem();
148110

149-
if (!$this->canRefundItem($orderItem, $qtys, $invoiceQtysRefundLimits)) {
111+
if (!$this->canRefundItem($orderItem, $qtyList, $invoiceRefundLimitsQtyList)) {
150112
continue;
151113
}
152114

153-
$item = $this->convertor->itemToCreditmemoItem($orderItem);
154-
if ($orderItem->isDummy()) {
155-
if (isset($data['qtys'][$orderItem->getParentItemId()])) {
156-
$parentQty = $data['qtys'][$orderItem->getParentItemId()];
157-
} else {
158-
$parentQty = $orderItem->getParentItem() ? $orderItem->getParentItem()->getQtyToRefund() : 1;
159-
}
160-
$qty = $this->calculateProductOptions($orderItem, $parentQty);
161-
} else {
162-
if (isset($qtys[$orderItem->getId()])) {
163-
$qty = (double)$qtys[$orderItem->getId()];
164-
} elseif (!count($qtys)) {
165-
$qty = $orderItem->getQtyToRefund();
166-
} else {
167-
continue;
168-
}
169-
if (isset($invoiceQtysRefundLimits[$orderItem->getId()])) {
170-
$qty = min($qty, $invoiceQtysRefundLimits[$orderItem->getId()]);
171-
}
172-
}
173-
$qty = min($qty, $invoiceItem->getQty());
115+
$qty = min(
116+
$this->getQtyToRefund($orderItem, $qtyList, $invoiceRefundLimitsQtyList),
117+
$invoiceItem->getQty()
118+
);
174119
$totalQty += $qty;
120+
$item = $this->convertor->itemToCreditmemoItem($orderItem);
175121
$item->setQty($qty);
176122
$creditmemo->addItem($item);
177123
}
178124
$creditmemo->setTotalQty($totalQty);
179125

180126
$this->initData($creditmemo, $data);
181127
if (!isset($data['shipping_amount'])) {
182-
$isShippingInclTax = $this->taxConfig->displaySalesShippingInclTax($order->getStoreId());
183-
if ($isShippingInclTax) {
184-
$baseAllowedAmount = $order->getBaseShippingInclTax() -
185-
$order->getBaseShippingRefunded() -
186-
$order->getBaseShippingTaxRefunded();
187-
} else {
188-
$baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded();
189-
$baseAllowedAmount = min($baseAllowedAmount, $invoice->getBaseShippingAmount());
190-
}
128+
$baseAllowedAmount = $this->getShippingAmount($invoice);
191129
$creditmemo->setBaseShippingAmount($baseAllowedAmount);
192130
}
193131

@@ -272,11 +210,11 @@ protected function initData($creditmemo, $data)
272210
}
273211

274212
/**
275-
* @param \Magento\Sales\Api\Data\OrderItemInterface $orderItem
213+
* @param Item $orderItem
276214
* @param int $parentQty
277215
* @return int
278216
*/
279-
private function calculateProductOptions(\Magento\Sales\Api\Data\OrderItemInterface $orderItem, $parentQty)
217+
private function calculateProductOptions(Item $orderItem, int $parentQty): int
280218
{
281219
$qty = $parentQty;
282220
$productOptions = $orderItem->getProductOptions();
@@ -290,4 +228,113 @@ private function calculateProductOptions(\Magento\Sales\Api\Data\OrderItemInterf
290228
}
291229
return $qty;
292230
}
231+
232+
/**
233+
* Gets list of quantities based on invoice refunded items.
234+
*
235+
* @param Invoice $invoice
236+
* @return array
237+
*/
238+
private function getInvoiceRefundedQtyList(Invoice $invoice): array
239+
{
240+
$invoiceRefundedQtyList = [];
241+
foreach ($invoice->getOrder()->getCreditmemosCollection() as $creditmemo) {
242+
if ($creditmemo->getState() !== Creditmemo::STATE_CANCELED &&
243+
$creditmemo->getInvoiceId() === $invoice->getId()
244+
) {
245+
foreach ($creditmemo->getAllItems() as $creditmemoItem) {
246+
$orderItemId = $creditmemoItem->getOrderItem()->getId();
247+
if (isset($invoiceRefundedQtyList[$orderItemId])) {
248+
$invoiceRefundedQtyList[$orderItemId] += $creditmemoItem->getQty();
249+
} else {
250+
$invoiceRefundedQtyList[$orderItemId] = $creditmemoItem->getQty();
251+
}
252+
}
253+
}
254+
}
255+
256+
return $invoiceRefundedQtyList;
257+
}
258+
259+
/**
260+
* Gets limits of refund based on invoice items.
261+
*
262+
* @param Invoice $invoice
263+
* @return array
264+
*/
265+
private function getInvoiceRefundLimitsQtyList(Invoice $invoice): array
266+
{
267+
$invoiceRefundLimitsQtyList = [];
268+
$invoiceRefundedQtyList = $this->getInvoiceRefundedQtyList($invoice);
269+
270+
foreach ($invoice->getAllItems() as $invoiceItem) {
271+
$qtyCanBeRefunded = $invoiceItem->getQty();
272+
$orderItemId = $invoiceItem->getOrderItem()->getId();
273+
if (isset($invoiceRefundedQtyList[$orderItemId])) {
274+
$qtyCanBeRefunded = $qtyCanBeRefunded - $invoiceRefundedQtyList[$orderItemId];
275+
}
276+
$invoiceRefundLimitsQtyList[$orderItemId] = $qtyCanBeRefunded;
277+
}
278+
279+
return $invoiceRefundLimitsQtyList;
280+
}
281+
282+
/**
283+
* Gets quantity of items to refund based on order item.
284+
*
285+
* @param Item $orderItem
286+
* @param array $qtyList
287+
* @param array $refundLimits
288+
* @return float
289+
*/
290+
private function getQtyToRefund(Item $orderItem, array $qtyList, array $refundLimits = []): float
291+
{
292+
$qty = 0;
293+
if ($orderItem->isDummy()) {
294+
if (isset($qtyList[$orderItem->getParentItemId()])) {
295+
$parentQty = $qtyList[$orderItem->getParentItemId()];
296+
} elseif ($orderItem->getProductType() === BundlePrice::PRODUCT_TYPE) {
297+
$parentQty = $orderItem->getQtyInvoiced();
298+
} else {
299+
$parentQty = $orderItem->getParentItem() ? $orderItem->getParentItem()->getQtyToRefund() : 1;
300+
}
301+
$qty = $this->calculateProductOptions($orderItem, $parentQty);
302+
} else {
303+
if (isset($qtyList[$orderItem->getId()])) {
304+
$qty = $qtyList[$orderItem->getId()];
305+
} elseif (!count($qtyList)) {
306+
$qty = $orderItem->getQtyToRefund();
307+
} else {
308+
return (float)$qty;
309+
}
310+
311+
if (isset($refundLimits[$orderItem->getId()])) {
312+
$qty = min($qty, $refundLimits[$orderItem->getId()]);
313+
}
314+
}
315+
316+
return (float)$qty;
317+
}
318+
319+
/**
320+
* Gets shipping amount based on invoice.
321+
*
322+
* @param Invoice $invoice
323+
* @return float
324+
*/
325+
private function getShippingAmount(Invoice $invoice): float
326+
{
327+
$order = $invoice->getOrder();
328+
$isShippingInclTax = $this->taxConfig->displaySalesShippingInclTax($order->getStoreId());
329+
if ($isShippingInclTax) {
330+
$amount = $order->getBaseShippingInclTax() -
331+
$order->getBaseShippingRefunded() -
332+
$order->getBaseShippingTaxRefunded();
333+
} else {
334+
$amount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded();
335+
$amount = min($amount, $invoice->getBaseShippingAmount());
336+
}
337+
338+
return (float)$amount;
339+
}
293340
}

app/code/Magento/Sales/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"magento/module-authorization": "*",
1111
"magento/module-backend": "*",
1212
"magento/module-catalog": "*",
13+
"magento/module-bundle": "*",
1314
"magento/module-catalog-inventory": "*",
1415
"magento/module-checkout": "*",
1516
"magento/module-config": "*",

0 commit comments

Comments
 (0)