Skip to content

Commit 2eccce2

Browse files
committed
12386: Fix Order Status resets to default Status after Partial Refund.
1 parent 9c36f6f commit 2eccce2

File tree

8 files changed

+309
-67
lines changed

8 files changed

+309
-67
lines changed

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

Lines changed: 86 additions & 59 deletions
Large diffs are not rendered by default.

app/code/Magento/Sales/Model/RefundOrder.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,13 @@ public function execute(
151151
$creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED);
152152
$order->setCustomerNoteNotify($notify);
153153
$order = $this->refundAdapter->refund($creditmemo, $order);
154-
$order->setState(
155-
$this->orderStateResolver->getStateForOrder($order, [])
156-
);
157-
$order->setStatus($this->config->getStateDefaultStatus($order->getState()));
154+
$orderState = $this->orderStateResolver->getStateForOrder($order, []);
155+
$order->setState($orderState);
156+
$statuses = $this->config->getStateStatuses($orderState, false);
157+
$status = in_array($order->getStatus(), $statuses, true)
158+
? $order->getStatus()
159+
: $this->config->getStateDefaultStatus($orderState);
160+
$order->setStatus($status);
158161

159162
$order = $this->orderRepository->save($order);
160163
$creditmemo = $this->creditmemoRepository->save($creditmemo);

app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ public function testRefund()
15261526
$this->orderStateResolver->expects($this->once())->method('getStateForOrder')
15271527
->with($this->order)
15281528
->willReturn(Order::STATE_CLOSED);
1529-
$this->mockGetDefaultStatus(Order::STATE_CLOSED, $status);
1529+
$this->mockGetDefaultStatus(Order::STATE_CLOSED, $status, ['first, second']);
15301530
$this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message);
15311531

15321532
static::assertSame($this->payment, $this->payment->refund($this->creditMemoMock));

app/code/Magento/Sales/Test/Unit/Model/RefundOrderTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ public function testOrderCreditmemo($orderId, $notify, $appendComment)
245245
->method('setState')
246246
->with(Order::STATE_CLOSED)
247247
->willReturnSelf();
248-
$this->orderMock->expects($this->once())
249-
->method('getState')
250-
->willReturn(Order::STATE_CLOSED);
248+
$this->configMock->expects($this->once())
249+
->method('getStateStatuses')
250+
->willReturn(['first, second']);
251251
$this->configMock->expects($this->once())
252252
->method('getStateDefaultStatus')
253253
->with(Order::STATE_CLOSED)

dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,73 @@ public function testFullRequest()
201201
}
202202
}
203203

204+
/**
205+
* Test order will keep same(custom) status after partial refund, if state has not been changed.
206+
*
207+
* @magentoApiDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php
208+
*/
209+
public function testOrderStatusPartialRefund()
210+
{
211+
/** @var \Magento\Sales\Model\Order $existingOrder */
212+
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
213+
->loadByIncrementId('100000001');
214+
215+
$items = $this->getOrderItems($existingOrder);
216+
$items[0]['qty'] -= 1;
217+
$result = $this->_webApiCall(
218+
$this->getServiceData($existingOrder),
219+
[
220+
'orderId' => $existingOrder->getEntityId(),
221+
'items' => $items,
222+
]
223+
);
224+
225+
$this->assertNotEmpty(
226+
$result,
227+
'Failed asserting that the received response is correct'
228+
);
229+
230+
/** @var \Magento\Sales\Model\Order $updatedOrder */
231+
$updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
232+
->loadByIncrementId($existingOrder->getIncrementId());
233+
234+
$this->assertSame('custom_processing', $updatedOrder->getStatus());
235+
$this->assertSame('processing', $updatedOrder->getState());
236+
}
237+
238+
/**
239+
* Test order will change custom status after total refund, when state has been changed.
240+
*
241+
* @magentoApiDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php
242+
*/
243+
public function testOrderStatusTotalRefund()
244+
{
245+
/** @var \Magento\Sales\Model\Order $existingOrder */
246+
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
247+
->loadByIncrementId('100000001');
248+
249+
$items = $this->getOrderItems($existingOrder);
250+
$result = $this->_webApiCall(
251+
$this->getServiceData($existingOrder),
252+
[
253+
'orderId' => $existingOrder->getEntityId(),
254+
'items' => $items,
255+
]
256+
);
257+
258+
$this->assertNotEmpty(
259+
$result,
260+
'Failed asserting that the received response is correct'
261+
);
262+
263+
/** @var \Magento\Sales\Model\Order $updatedOrder */
264+
$updatedOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
265+
->loadByIncrementId($existingOrder->getIncrementId());
266+
267+
$this->assertSame('complete', $updatedOrder->getStatus());
268+
$this->assertSame('complete', $updatedOrder->getState());
269+
}
270+
204271
/**
205272
* Prepares and returns info for API service.
206273
*
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Sales\Controller\Adminhtml\Order\Creditmemo;
9+
10+
use Magento\Framework\App\Request\Http as HttpRequest;
11+
use Magento\Sales\Api\Data\OrderItemInterface;
12+
use Magento\Sales\Model\Order;
13+
use Magento\TestFramework\TestCase\AbstractBackendController;
14+
15+
/**
16+
* Provide tests for CreditMemo save controller.
17+
*
18+
* @magentoAppArea adminhtml
19+
*/
20+
class SaveTest extends AbstractBackendController
21+
{
22+
/**
23+
* Test order will keep same(custom) status after partial refund, if state has not been changed.
24+
*
25+
* @magentoDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php
26+
*/
27+
public function testOrderStatusPartialRefund()
28+
{
29+
/** @var Order $existingOrder */
30+
$existingOrder = $this->_objectManager->create(Order::class)->loadByIncrementId('100000001');
31+
$items = $this->getOrderItems($existingOrder, 1);
32+
$requestParams = [
33+
'creditmemo' => [
34+
'items' => $items,
35+
'do_offline' => '1',
36+
'comment_text' => '',
37+
'shipping_amount' => '0',
38+
'adjustment_positive' => '0',
39+
'adjustment_negative' => '0',
40+
],
41+
'order_id' => $existingOrder->getId(),
42+
];
43+
$this->getRequest()->setMethod(HttpRequest::METHOD_POST);
44+
$this->getRequest()->setParams($requestParams);
45+
$this->dispatch('backend/sales/order_creditmemo/save');
46+
47+
/** @var Order $updatedOrder */
48+
$updatedOrder = $this->_objectManager->create(Order::class)
49+
->loadByIncrementId($existingOrder->getIncrementId());
50+
51+
$this->assertSame('custom_processing', $updatedOrder->getStatus());
52+
$this->assertSame('processing', $updatedOrder->getState());
53+
}
54+
55+
/**
56+
* Test order will change custom status after total refund, when state has been changed.
57+
*
58+
* @magentoDataFixture Magento/Sales/_files/order_with_invoice_and_custom_status.php
59+
*/
60+
public function testOrderStatusTotalRefund()
61+
{
62+
/** @var Order $existingOrder */
63+
$existingOrder = $this->_objectManager->create(Order::class)->loadByIncrementId('100000001');
64+
$requestParams = [
65+
'creditmemo' => [
66+
'items' => $this->getOrderItems($existingOrder),
67+
'do_offline' => '1',
68+
'comment_text' => '',
69+
'shipping_amount' => '0',
70+
'adjustment_positive' => '0',
71+
'adjustment_negative' => '0',
72+
],
73+
'order_id' => $existingOrder->getId(),
74+
];
75+
$this->getRequest()->setMethod(HttpRequest::METHOD_POST);
76+
$this->getRequest()->setParams($requestParams);
77+
$this->dispatch('backend/sales/order_creditmemo/save');
78+
79+
/** @var Order $updatedOrder */
80+
$updatedOrder = $this->_objectManager->create(Order::class)
81+
->loadByIncrementId($existingOrder->getIncrementId());
82+
83+
$this->assertSame('complete', $updatedOrder->getStatus());
84+
$this->assertSame('complete', $updatedOrder->getState());
85+
}
86+
87+
/**
88+
* Gets all items of given Order in proper format.
89+
*
90+
* @param Order $order
91+
* @param int $subQty
92+
* @return array
93+
*/
94+
private function getOrderItems(Order $order, int $subQty = 0)
95+
{
96+
$items = [];
97+
/** @var OrderItemInterface $item */
98+
foreach ($order->getAllItems() as $item) {
99+
$items[$item->getItemId()] = [
100+
'qty' => $item->getQtyOrdered() - $subQty,
101+
];
102+
}
103+
104+
return $items;
105+
}
106+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Sales\Model\Order\Status;
9+
use Magento\TestFramework\Helper\Bootstrap;
10+
11+
require 'invoice.php';
12+
13+
$orderStatus = Bootstrap::getObjectManager()->create(Status::class);
14+
$data = [
15+
'status' => 'custom_processing',
16+
'label' => 'Custom Processing Status',
17+
];
18+
$orderStatus->setData($data)->setStatus('custom_processing');
19+
$orderStatus->save();
20+
$orderStatus->assignState('processing');
21+
22+
$order->setStatus('custom_processing');
23+
$order->save();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Sales\Model\Order\Status;
9+
use Magento\TestFramework\Helper\Bootstrap;
10+
11+
require 'default_rollback.php';
12+
13+
/** @var Status $orderStatus */
14+
$orderStatus = Bootstrap::getObjectManager()->create(Status::class);
15+
$orderStatus->load('custom_processing', 'status');
16+
$orderStatus->delete();

0 commit comments

Comments
 (0)