Skip to content

Commit c0b8b8b

Browse files
author
olysenko
committed
MAGETWO-64120: Error processing your request when placing reorder for simple product of configurable if attribute is changed
1 parent b651e69 commit c0b8b8b

File tree

5 files changed

+560
-4
lines changed

5 files changed

+560
-4
lines changed

app/code/Magento/Sales/Controller/Adminhtml/Order/Create/Reorder.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
use Magento\Backend\App\Action;
99
use Magento\Backend\Model\View\Result\ForwardFactory;
1010
use Magento\Framework\View\Result\PageFactory;
11-
use \Magento\Sales\Model\Order\Reorder\UnavailableProductsProvider;
11+
use Magento\Sales\Model\Order\Reorder\UnavailableProductsProvider;
12+
use Magento\Sales\Api\OrderRepositoryInterface;
13+
use Magento\Sales\Helper\Reorder as ReorderHelper;
1214

1315
class Reorder extends \Magento\Sales\Controller\Adminhtml\Order\Create
1416
{
@@ -17,8 +19,20 @@ class Reorder extends \Magento\Sales\Controller\Adminhtml\Order\Create
1719
*/
1820
private $unavailableProductsProvider;
1921

22+
/**
23+
* @var OrderRepositoryInterface
24+
*/
25+
private $orderRepository;
26+
27+
/**
28+
* @var ReorderHelper
29+
*/
30+
private $reorderHelper;
31+
2032
/**
2133
* @param UnavailableProductsProvider $unavailableProductsProvider
34+
* @param OrderRepositoryInterface $orderRepository
35+
* @param ReorderHelper $reorderHelper
2236
* @param Action\Context $context
2337
* @param \Magento\Catalog\Helper\Product $productHelper
2438
* @param \Magento\Framework\Escaper $escaper
@@ -27,13 +41,17 @@ class Reorder extends \Magento\Sales\Controller\Adminhtml\Order\Create
2741
*/
2842
public function __construct(
2943
UnavailableProductsProvider $unavailableProductsProvider,
44+
OrderRepositoryInterface $orderRepository,
45+
ReorderHelper $reorderHelper,
3046
Action\Context $context,
3147
\Magento\Catalog\Helper\Product $productHelper,
3248
\Magento\Framework\Escaper $escaper,
3349
PageFactory $resultPageFactory,
3450
ForwardFactory $resultForwardFactory
3551
) {
3652
$this->unavailableProductsProvider = $unavailableProductsProvider;
53+
$this->orderRepository = $orderRepository;
54+
$this->reorderHelper = $reorderHelper;
3755
parent::__construct(
3856
$context,
3957
$productHelper,
@@ -50,15 +68,17 @@ public function execute()
5068
{
5169
$this->_getSession()->clearStorage();
5270
$orderId = $this->getRequest()->getParam('order_id');
53-
$order = $this->_objectManager->create(\Magento\Sales\Model\Order::class)->load($orderId);
54-
if (!$this->_objectManager->get(\Magento\Sales\Helper\Reorder::class)->canReorder($order->getEntityId())) {
71+
/** @var \Magento\Sales\Model\Order $order */
72+
$order = $this->orderRepository->get($orderId);
73+
if (!$this->reorderHelper->canReorder($order->getEntityId())) {
5574
return $this->resultForwardFactory->create()->forward('noroute');
5675
}
5776

5877
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
5978
$resultRedirect = $this->resultRedirectFactory->create();
6079
if (!$order->getId()) {
6180
$resultRedirect->setPath('sales/order/');
81+
return $resultRedirect;
6282
}
6383

6484
$unavailableProducts = $this->unavailableProductsProvider->getForOrder($order);

app/code/Magento/Sales/Model/Order/Reorder/OrderedProductAvailabilityChecker.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function isAvailable(Item $item)
4141
if (!$checkForType instanceof OrderedProductAvailabilityCheckerInterface) {
4242
throw new ConfigurationMismatchException(__('Received check doesn\'t match interface'));
4343
}
44-
return $checkForType->checkAvailability($item);
44+
return $checkForType->isAvailable($item);
4545
} else {
4646
return true;
4747
}
Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order\Create;
7+
8+
use Magento\Backend\App\Action\Context;
9+
use Magento\Backend\Model\Session\Quote;
10+
use Magento\Backend\Model\View\Result\Forward;
11+
use Magento\Backend\Model\View\Result\ForwardFactory;
12+
use Magento\Backend\Model\View\Result\Redirect;
13+
use Magento\Backend\Model\View\Result\RedirectFactory;
14+
use Magento\Framework\App\RequestInterface;
15+
use Magento\Framework\Message\ManagerInterface;
16+
use Magento\Framework\ObjectManagerInterface;
17+
use Magento\Sales\Api\OrderRepositoryInterface;
18+
use Magento\Sales\Controller\Adminhtml\Order\Create\Reorder;
19+
use Magento\Sales\Model\AdminOrder\Create;
20+
use Magento\Sales\Model\Order;
21+
use Magento\Sales\Model\Order\Reorder\UnavailableProductsProvider;
22+
use Magento\Sales\Helper\Reorder as ReorderHelper;
23+
24+
/**
25+
* Class ReorderTest
26+
*/
27+
class ReorderTest extends \PHPUnit_Framework_TestCase
28+
{
29+
/**
30+
* @var Reorder
31+
*/
32+
private $reorder;
33+
34+
/**
35+
* @var Context
36+
*/
37+
private $context;
38+
39+
/**
40+
* @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject
41+
*/
42+
private $requestMock;
43+
44+
/**
45+
* @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject
46+
*/
47+
private $objectManagerMock;
48+
49+
/**
50+
* @var Order|\PHPUnit_Framework_MockObject_MockObject
51+
*/
52+
private $orderMock;
53+
54+
/**
55+
* @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
56+
*/
57+
private $messageManagerMock;
58+
59+
/**
60+
* @var ForwardFactory|\PHPUnit_Framework_MockObject_MockObject
61+
*/
62+
private $resultForwardFactoryMock;
63+
64+
/**
65+
* @var RedirectFactory|\PHPUnit_Framework_MockObject_MockObject
66+
*/
67+
private $resultRedirectFactoryMock;
68+
69+
/**
70+
* @var Redirect|\PHPUnit_Framework_MockObject_MockObject
71+
*/
72+
private $resultRedirectMock;
73+
74+
/**
75+
* @var Forward|\PHPUnit_Framework_MockObject_MockObject
76+
*/
77+
private $resultForwardMock;
78+
79+
/**
80+
* @var Quote|\PHPUnit_Framework_MockObject_MockObject
81+
*/
82+
private $quoteSessionMock;
83+
84+
/**
85+
* @var OrderRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
86+
*/
87+
private $orderRepositoryMock;
88+
89+
/**
90+
* @var ReorderHelper|\PHPUnit_Framework_MockObject_MockObject
91+
*/
92+
private $reorderHelperMock;
93+
94+
/**
95+
* @var UnavailableProductsProvider|\PHPUnit_Framework_MockObject_MockObject
96+
*/
97+
private $unavailableProductsProviderMock;
98+
99+
/**
100+
* @var Create|\PHPUnit_Framework_MockObject_MockObject
101+
*/
102+
private $orderCreateMock;
103+
104+
/**
105+
* @var int
106+
*/
107+
private $orderId;
108+
109+
protected function setUp()
110+
{
111+
$this->orderId = 111;
112+
$this->orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class)->getMockForAbstractClass();
113+
$this->orderMock = $this->getMockBuilder(Order::class)
114+
->disableOriginalConstructor()
115+
->setMethods(['getEntityId', 'getId', 'setReordered'])
116+
->getMock();
117+
$this->requestMock = $this->getMockBuilder(RequestInterface::class)->getMockForAbstractClass();
118+
$this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class)->getMockForAbstractClass();
119+
$this->resultForwardFactoryMock = $this->getMockBuilder(ForwardFactory::class)->getMock();
120+
$this->resultRedirectFactoryMock = $this->getMockBuilder(RedirectFactory::class)
121+
->disableOriginalConstructor()
122+
->getMock();
123+
$this->resultRedirectMock = $this->getMockBuilder(Redirect::class)->disableOriginalConstructor()->getMock();
124+
$this->resultForwardMock = $this->getMockBuilder(Forward::class)->disableOriginalConstructor()->getMock();
125+
$this->quoteSessionMock = $this->getMockBuilder(Quote::class)
126+
->disableOriginalConstructor()
127+
->setMethods(['clearStorage', 'setUseOldShippingMethod'])
128+
->getMock();
129+
$this->reorderHelperMock = $this->getMockBuilder(ReorderHelper::class)
130+
->disableOriginalConstructor()
131+
->getMock();
132+
$this->messageManagerMock = $this->getMockBuilder(ManagerInterface::class)->getMockForAbstractClass();
133+
$this->unavailableProductsProviderMock = $this->getMockBuilder(UnavailableProductsProvider::class)
134+
->disableOriginalConstructor()
135+
->getMock();
136+
$this->orderCreateMock = $this->getMockBuilder(Create::class)->disableOriginalConstructor()->getMock();
137+
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
138+
$this->context = $objectManager->getObject(
139+
Context::class,
140+
[
141+
'request' => $this->requestMock,
142+
'objectManager' => $this->objectManagerMock,
143+
'messageManager' => $this->messageManagerMock,
144+
'resultRedirectFactory' => $this->resultRedirectFactoryMock
145+
]
146+
);
147+
148+
$this->reorder = $objectManager->getObject(
149+
Reorder::class,
150+
[
151+
'unavailableProductsProvider' => $this->unavailableProductsProviderMock,
152+
'orderRepository' => $this->orderRepositoryMock,
153+
'reorderHelper' => $this->reorderHelperMock,
154+
'context' => $this->context,
155+
'resultForwardFactory' => $this->resultForwardFactoryMock,
156+
]
157+
);
158+
}
159+
160+
public function testExecuteForward()
161+
{
162+
$this->clearStorage();
163+
$this->getOrder();
164+
$this->canReorder(false);
165+
$this->prepareForward();
166+
167+
$this->assertInstanceOf(Forward::class, $this->reorder->execute());
168+
}
169+
170+
public function testExecuteRedirectOrderGrid()
171+
{
172+
$this->clearStorage();
173+
$this->getOrder();
174+
$this->canReorder(true);
175+
$this->createRedirect();
176+
$this->getOrderId(null);
177+
$this->setPath('sales/order/');
178+
179+
$this->assertInstanceOf(Redirect::class, $this->reorder->execute());
180+
}
181+
182+
public function testExecuteRedirectBack()
183+
{
184+
$this->clearStorage();
185+
$this->getOrder();
186+
$this->canReorder(true);
187+
$this->createRedirect();
188+
$this->getOrderId($this->orderId);
189+
$this->getUnavailableProducts([1, 3]);
190+
$this->messageManagerMock->expects($this->any())->method('addNoticeMessage');
191+
$this->setPath('sales/order/view', ['order_id' => $this->orderId]);
192+
193+
$this->assertInstanceOf(Redirect::class, $this->reorder->execute());
194+
}
195+
196+
public function testExecuteRedirectNewOrder()
197+
{
198+
$this->clearStorage();
199+
$this->getOrder();
200+
$this->canReorder(true);
201+
$this->createRedirect();
202+
$this->getOrderId($this->orderId);
203+
$this->getUnavailableProducts([]);
204+
$this->initFromOrder();
205+
$this->setPath('sales/*');
206+
207+
$this->assertInstanceOf(Redirect::class, $this->reorder->execute());
208+
}
209+
210+
private function clearStorage()
211+
{
212+
$this->objectManagerMock->expects($this->at(0))
213+
->method('get')
214+
->with(Quote::class)
215+
->willReturn($this->quoteSessionMock);
216+
$this->quoteSessionMock->expects($this->once())->method('clearStorage')->will($this->returnSelf());
217+
}
218+
219+
private function getOrder()
220+
{
221+
$this->requestMock->expects($this->once())
222+
->method('getParam')
223+
->with('order_id')
224+
->willReturn($this->orderId);
225+
$this->orderRepositoryMock->expects($this->once())
226+
->method('get')
227+
->with($this->orderId)
228+
->willReturn($this->orderMock);
229+
}
230+
231+
/**
232+
* @param bool $result
233+
*/
234+
private function canReorder($result)
235+
{
236+
$entity_id = 1;
237+
$this->orderMock->expects($this->once())->method('getEntityId')->willReturn($entity_id);
238+
$this->reorderHelperMock->expects($this->once())
239+
->method('canReorder')
240+
->with($entity_id)
241+
->willReturn($result);
242+
}
243+
244+
private function prepareForward()
245+
{
246+
$this->resultForwardFactoryMock->expects($this->once())->method('create')->willReturn($this->resultForwardMock);
247+
$this->resultForwardMock->expects($this->once())->method('forward')->with('noroute')->willReturnSelf();
248+
}
249+
250+
private function createRedirect()
251+
{
252+
$this->resultRedirectFactoryMock->expects($this->once())
253+
->method('create')
254+
->willReturn($this->resultRedirectMock);
255+
}
256+
257+
/**
258+
* @param null|int $orderId
259+
*/
260+
private function getOrderId($orderId)
261+
{
262+
$this->orderMock->expects($this->once())->method('getId')->willReturn($orderId);
263+
}
264+
265+
/**
266+
* @param string $path
267+
* @param null|array $params
268+
*/
269+
private function setPath($path, $params = [])
270+
{
271+
$this->resultRedirectMock->expects($this->once())->method('setPath')->with($path, $params);
272+
}
273+
274+
/**
275+
* @param array $unavailableProducts
276+
*/
277+
private function getUnavailableProducts(array $unavailableProducts)
278+
{
279+
$this->unavailableProductsProviderMock->expects($this->any())
280+
->method('getForOrder')
281+
->with($this->orderMock)
282+
->willReturn($unavailableProducts);
283+
}
284+
285+
private function initFromOrder()
286+
{
287+
$this->orderMock->expects($this->once())->method('setReordered')->with(true)->willReturnSelf();
288+
$this->objectManagerMock->expects($this->at(1))
289+
->method('get')
290+
->with(Quote::class)
291+
->willReturn($this->quoteSessionMock);
292+
$this->quoteSessionMock->expects($this->once())
293+
->method('setUseOldShippingMethod')
294+
->with(true)
295+
->will($this->returnSelf());
296+
$this->objectManagerMock->expects($this->at(2))
297+
->method('get')
298+
->with(Create::class)
299+
->willReturn($this->orderCreateMock);
300+
$this->orderCreateMock->expects($this->once())
301+
->method('initFromOrder')
302+
->with($this->orderMock)
303+
->willReturnSelf();
304+
}
305+
}

0 commit comments

Comments
 (0)