Skip to content

Commit 8ad436c

Browse files
author
Stanislav Idolov
authored
ENGCOM-3094: [Backport 2.2-develop] Refactor Mass Order Cancel code to use Interface #18377
2 parents d59eb89 + 6ca6064 commit 8ad436c

File tree

2 files changed

+310
-5
lines changed

2 files changed

+310
-5
lines changed

app/code/Magento/Sales/Controller/Adminhtml/Order/MassCancel.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,37 @@
1111
use Magento\Ui\Component\MassAction\Filter;
1212
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
1313
use Magento\Framework\App\Request\Http as HttpRequest;
14+
use Magento\Sales\Api\OrderManagementInterface;
1415

1516
class MassCancel extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
1617
{
1718
/**
1819
* Authorization level of a basic admin session
1920
*/
2021
const ADMIN_RESOURCE = 'Magento_Sales::cancel';
22+
23+
/**
24+
* @var OrderManagementInterface
25+
*/
26+
private $orderManagement;
2127

2228
/**
2329
* @param Context $context
2430
* @param Filter $filter
2531
* @param CollectionFactory $collectionFactory
32+
* @param OrderManagementInterface|null $orderManagement
2633
*/
27-
public function __construct(Context $context, Filter $filter, CollectionFactory $collectionFactory)
28-
{
34+
public function __construct(
35+
Context $context,
36+
Filter $filter,
37+
CollectionFactory $collectionFactory,
38+
OrderManagementInterface $orderManagement = null
39+
) {
2940
parent::__construct($context, $filter);
3041
$this->collectionFactory = $collectionFactory;
42+
$this->orderManagement = $orderManagement ?: \Magento\Framework\App\ObjectManager::getInstance()->get(
43+
\Magento\Sales\Api\OrderManagementInterface::class
44+
);
3145
}
3246

3347
/**
@@ -54,11 +68,10 @@ protected function massAction(AbstractCollection $collection)
5468
{
5569
$countCancelOrder = 0;
5670
foreach ($collection->getItems() as $order) {
57-
if (!$order->canCancel()) {
71+
$isCanceled = $this->orderManagement->cancel($order->getEntityId());
72+
if ($isCanceled === false) {
5873
continue;
5974
}
60-
$order->cancel();
61-
$order->save();
6275
$countCancelOrder++;
6376
}
6477
$countNonCancelOrder = $collection->count() - $countCancelOrder;
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order;
8+
9+
use Magento\Framework\App\Action\Context;
10+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
11+
12+
/**
13+
* Class MassCancelTest
14+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
15+
*/
16+
class MassCancelTest extends \PHPUnit\Framework\TestCase
17+
{
18+
/**
19+
* @var \Magento\Sales\Controller\Adminhtml\Order\MassCancel
20+
*/
21+
protected $massAction;
22+
23+
/**
24+
* @var Context|\PHPUnit_Framework_MockObject_MockObject
25+
*/
26+
protected $contextMock;
27+
28+
/**
29+
* @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject
30+
*/
31+
protected $resultRedirectMock;
32+
33+
/**
34+
* @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject
35+
*/
36+
protected $requestMock;
37+
38+
/**
39+
* @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject
40+
*/
41+
protected $responseMock;
42+
43+
/**
44+
* @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject
45+
*/
46+
protected $messageManagerMock;
47+
48+
/**
49+
* @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject
50+
*/
51+
protected $objectManagerMock;
52+
53+
/**
54+
* @var \Magento\Backend\Model\Session|\PHPUnit_Framework_MockObject_MockObject
55+
*/
56+
protected $sessionMock;
57+
58+
/**
59+
* @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject
60+
*/
61+
protected $actionFlagMock;
62+
63+
/**
64+
* @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject
65+
*/
66+
protected $helperMock;
67+
68+
/**
69+
* @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject
70+
*/
71+
protected $orderMock;
72+
73+
/**
74+
* @var \Magento\Sales\Model\ResourceModel\Order\Collection|\PHPUnit_Framework_MockObject_MockObject
75+
*/
76+
protected $orderCollectionMock;
77+
78+
/**
79+
* @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
80+
*/
81+
protected $orderCollectionFactoryMock;
82+
83+
/**
84+
* @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject
85+
*/
86+
protected $filterMock;
87+
88+
/**
89+
* @var \PHPUnit_Framework_MockObject_MockObject
90+
*/
91+
private $orderManagementMock;
92+
93+
protected function setUp()
94+
{
95+
$objectManagerHelper = new ObjectManagerHelper($this);
96+
$this->contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class);
97+
$this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class);
98+
$this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class);
99+
$this->requestMock = $this->createMock(\Magento\Framework\App\Request\Http::class);
100+
$this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class);
101+
102+
$resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class);
103+
104+
$this->orderCollectionMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Collection::class)
105+
->disableOriginalConstructor()
106+
->getMock();
107+
108+
$resourceCollection = \Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class;
109+
$this->orderCollectionFactoryMock = $this->getMockBuilder($resourceCollection)
110+
->disableOriginalConstructor()
111+
->setMethods(['create'])
112+
->getMock();
113+
114+
$this->sessionMock = $this->createPartialMock(\Magento\Backend\Model\Session::class, ['setIsUrlNotice']);
115+
$this->actionFlagMock = $this->createPartialMock(\Magento\Framework\App\ActionFlag::class, ['get', 'set']);
116+
$this->helperMock = $this->createPartialMock(\Magento\Backend\Helper\Data::class, ['getUrl']);
117+
$this->resultRedirectMock = $this->createMock(\Magento\Backend\Model\View\Result\Redirect::class);
118+
$resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock);
119+
120+
$redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class)
121+
->disableOriginalConstructor()
122+
->getMock();
123+
124+
$resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class)
125+
->disableOriginalConstructor()
126+
->getMock();
127+
$resultFactoryMock->expects($this->any())
128+
->method('create')
129+
->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT)
130+
->willReturn($redirectMock);
131+
132+
$this->requestMock->expects($this->once())->method('isPost')->willReturn(true);
133+
$this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock);
134+
$this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock);
135+
$this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock);
136+
$this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock);
137+
$this->contextMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock);
138+
$this->contextMock->expects($this->once())->method('getActionFlag')->willReturn($this->actionFlagMock);
139+
$this->contextMock->expects($this->once())->method('getHelper')->willReturn($this->helperMock);
140+
$this->contextMock->expects($this->once())
141+
->method('getResultRedirectFactory')
142+
->willReturn($resultRedirectFactory);
143+
$this->contextMock->expects($this->any())
144+
->method('getResultFactory')
145+
->willReturn($resultFactoryMock);
146+
$this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class);
147+
$this->filterMock->expects($this->once())
148+
->method('getCollection')
149+
->with($this->orderCollectionMock)
150+
->willReturn($this->orderCollectionMock);
151+
$this->orderCollectionFactoryMock->expects($this->once())
152+
->method('create')
153+
->willReturn($this->orderCollectionMock);
154+
$this->orderManagementMock = $this->createMock(\Magento\Sales\Api\OrderManagementInterface::class);
155+
156+
$this->massAction = $objectManagerHelper->getObject(
157+
\Magento\Sales\Controller\Adminhtml\Order\MassCancel::class,
158+
[
159+
'context' => $this->contextMock,
160+
'filter' => $this->filterMock,
161+
'collectionFactory' => $this->orderCollectionFactoryMock,
162+
'orderManagement' => $this->orderManagementMock
163+
]
164+
);
165+
}
166+
167+
/**
168+
* Test for selected orders
169+
* Two orders, only $order1 can be canceled
170+
*/
171+
public function testExecuteCanCancelOneOrder()
172+
{
173+
$order1id = 100;
174+
$order2id = 200;
175+
176+
$order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
177+
->disableOriginalConstructor()
178+
->getMock();
179+
$order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
180+
->disableOriginalConstructor()
181+
->getMock();
182+
$orders = [$order1, $order2];
183+
$countOrders = count($orders);
184+
185+
$this->orderCollectionMock->expects($this->any())
186+
->method('getItems')
187+
->willReturn($orders);
188+
189+
$order1->expects($this->once())
190+
->method('getEntityId')
191+
->willReturn($order1id);
192+
193+
$order2->expects($this->once())
194+
->method('getEntityId')
195+
->willReturn($order2id);
196+
197+
$this->orderCollectionMock->expects($this->once())
198+
->method('count')
199+
->willReturn($countOrders);
200+
201+
$this->orderManagementMock->expects($this->at(0))->method('cancel')->with($order1id)->willReturn(true);
202+
$this->orderManagementMock->expects($this->at(1))->method('cancel')->with($order2id)->willReturn(false);
203+
204+
$this->messageManagerMock->expects($this->once())
205+
->method('addError')
206+
->with('1 order(s) cannot be canceled.');
207+
208+
$this->messageManagerMock->expects($this->once())
209+
->method('addSuccess')
210+
->with('We canceled 1 order(s).');
211+
212+
$this->resultRedirectMock->expects($this->once())
213+
->method('setPath')
214+
->with('sales/*/')
215+
->willReturnSelf();
216+
217+
$this->massAction->execute();
218+
}
219+
220+
/**
221+
* Test for excluded orders
222+
* Two orders could't be canceled
223+
*/
224+
public function testExcludedCannotCancelOrders()
225+
{
226+
$order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
227+
->disableOriginalConstructor()
228+
->getMock();
229+
$order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
230+
->disableOriginalConstructor()
231+
->getMock();
232+
233+
$orders = [$order1, $order2];
234+
$countOrders = count($orders);
235+
236+
$order1->expects($this->once())
237+
->method('getEntityId')
238+
->willReturn(100);
239+
240+
$order2->expects($this->once())
241+
->method('getEntityId')
242+
->willReturn(200);
243+
244+
$this->orderCollectionMock->expects($this->any())
245+
->method('getItems')
246+
->willReturn([$order1, $order2]);
247+
248+
$this->orderCollectionMock->expects($this->once())
249+
->method('count')
250+
->willReturn($countOrders);
251+
252+
$this->orderManagementMock->expects($this->atLeastOnce())->method('cancel')->willReturn(false);
253+
254+
$this->messageManagerMock->expects($this->once())
255+
->method('addError')
256+
->with('You cannot cancel the order(s).');
257+
258+
$this->resultRedirectMock->expects($this->once())
259+
->method('setPath')
260+
->with('sales/*/')
261+
->willReturnSelf();
262+
263+
$this->massAction->execute();
264+
}
265+
266+
/**
267+
* Order throws exception while canceling
268+
*/
269+
public function testException()
270+
{
271+
$exception = new \Exception('Can not cancel');
272+
273+
$order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
274+
->disableOriginalConstructor()
275+
->getMock();
276+
$this->orderCollectionMock->expects($this->any())
277+
->method('getItems')
278+
->willReturn([$order1]);
279+
280+
$order1->expects($this->once())
281+
->method('getEntityId')
282+
->willReturn(100);
283+
284+
$this->orderManagementMock->expects($this->atLeastOnce())->method('cancel')->willThrowException($exception);
285+
286+
$this->messageManagerMock->expects($this->once())
287+
->method('addError')
288+
->with('Can not cancel');
289+
290+
$this->massAction->execute();
291+
}
292+
}

0 commit comments

Comments
 (0)