Skip to content

Commit c3ed36d

Browse files
committed
Merge branch 'ACP2E-694' of https://github.com/magento-l3/magento2ce into L3-PR-2022-04-19-v2
2 parents 82409c4 + 37bbfd1 commit c3ed36d

File tree

4 files changed

+179
-31
lines changed

4 files changed

+179
-31
lines changed

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

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\Sales\Model;
88

9+
use Magento\Framework\App\ObjectManager;
910
use Magento\Framework\App\ResourceConnection;
1011
use Magento\Sales\Api\CreditmemoRepositoryInterface;
1112
use Magento\Sales\Api\OrderRepositoryInterface;
@@ -19,7 +20,7 @@
1920
use Psr\Log\LoggerInterface;
2021

2122
/**
22-
* Class RefundOrder
23+
* Class RefundOrder for an order
2324
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2425
*/
2526
class RefundOrder implements RefundOrderInterface
@@ -74,6 +75,11 @@ class RefundOrder implements RefundOrderInterface
7475
*/
7576
private $logger;
7677

78+
/**
79+
* @var OrderMutexInterface
80+
*/
81+
private $orderMutex;
82+
7783
/**
7884
* RefundOrder constructor.
7985
*
@@ -87,6 +93,7 @@ class RefundOrder implements RefundOrderInterface
8793
* @param NotifierInterface $notifier
8894
* @param OrderConfig $config
8995
* @param LoggerInterface $logger
96+
* @param OrderMutex|null $orderMutex
9097
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
9198
*/
9299
public function __construct(
@@ -99,7 +106,8 @@ public function __construct(
99106
RefundOrderValidator $validator,
100107
NotifierInterface $notifier,
101108
OrderConfig $config,
102-
LoggerInterface $logger
109+
LoggerInterface $logger,
110+
?OrderMutexInterface $orderMutex = null
103111
) {
104112
$this->resourceConnection = $resourceConnection;
105113
$this->orderStateResolver = $orderStateResolver;
@@ -111,6 +119,7 @@ public function __construct(
111119
$this->notifier = $notifier;
112120
$this->config = $config;
113121
$this->logger = $logger;
122+
$this->orderMutex = $orderMutex ?: ObjectManager::getInstance()->get(OrderMutexInterface::class);
114123
}
115124

116125
/**
@@ -124,7 +133,45 @@ public function execute(
124133
\Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
125134
\Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
126135
) {
127-
$connection = $this->resourceConnection->getConnection('sales');
136+
return $this->orderMutex->execute(
137+
(int) $orderId,
138+
\Closure::fromCallable([$this, 'createRefund']),
139+
[
140+
$orderId,
141+
$items,
142+
$notify,
143+
$appendComment,
144+
$comment,
145+
$arguments
146+
]
147+
);
148+
}
149+
150+
/**
151+
* Creates refund for provided order ID
152+
*
153+
* @param int $orderId
154+
* @param array $items
155+
* @param bool $notify
156+
* @param bool $appendComment
157+
* @param \Magento\Sales\Api\Data\InvoiceCommentCreationInterface|null $comment
158+
* @param \Magento\Sales\Api\Data\InvoiceCreationArgumentsInterface|null $arguments
159+
* @return int
160+
* @throws \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface
161+
* @throws \Magento\Sales\Api\Exception\CouldNotRefundException
162+
* @throws \Magento\Framework\Exception\InputException
163+
* @throws \Magento\Framework\Exception\NoSuchEntityException
164+
* @throws \DomainException
165+
* @SuppressWarnings(PHPMD.UnusedPrivateMethod)
166+
*/
167+
private function createRefund(
168+
$orderId,
169+
array $items = [],
170+
$notify = false,
171+
$appendComment = false,
172+
\Magento\Sales\Api\Data\CreditmemoCommentCreationInterface $comment = null,
173+
\Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface $arguments = null
174+
) {
128175
$order = $this->orderRepository->get($orderId);
129176
$creditmemo = $this->creditmemoDocumentFactory->createFromOrder(
130177
$order,
@@ -147,7 +194,6 @@ public function execute(
147194
__("Creditmemo Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages()))
148195
);
149196
}
150-
$connection->beginTransaction();
151197
try {
152198
$creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED);
153199
$order->setCustomerNoteNotify($notify);
@@ -162,10 +208,8 @@ public function execute(
162208

163209
$order = $this->orderRepository->save($order);
164210
$creditmemo = $this->creditmemoRepository->save($creditmemo);
165-
$connection->commit();
166211
} catch (\Exception $e) {
167212
$this->logger->critical($e);
168-
$connection->rollBack();
169213
throw new \Magento\Sales\Exception\CouldNotRefundException(
170214
__('Could not save a Creditmemo, see error log for details')
171215
);

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

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Sales\Model;
77

8+
use Magento\Framework\App\ObjectManager;
89
use Magento\Framework\App\ResourceConnection;
910
use Magento\Sales\Api\OrderRepositoryInterface;
1011
use Magento\Sales\Api\ShipmentRepositoryInterface;
@@ -75,6 +76,11 @@ class ShipOrder implements ShipOrderInterface
7576
*/
7677
private $orderRegistrar;
7778

79+
/**
80+
* @var OrderMutexInterface
81+
*/
82+
private $orderMutex;
83+
7884
/**
7985
* @param ResourceConnection $resourceConnection
8086
* @param OrderRepositoryInterface $orderRepository
@@ -86,6 +92,7 @@ class ShipOrder implements ShipOrderInterface
8692
* @param NotifierInterface $notifierInterface
8793
* @param OrderRegistrarInterface $orderRegistrar
8894
* @param LoggerInterface $logger
95+
* @param OrderMutex|null $orderMutex
8996
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
9097
*/
9198
public function __construct(
@@ -98,7 +105,8 @@ public function __construct(
98105
ShipOrderValidator $shipOrderValidator,
99106
NotifierInterface $notifierInterface,
100107
OrderRegistrarInterface $orderRegistrar,
101-
LoggerInterface $logger
108+
LoggerInterface $logger,
109+
?OrderMutexInterface $orderMutex = null
102110
) {
103111
$this->resourceConnection = $resourceConnection;
104112
$this->orderRepository = $orderRepository;
@@ -110,6 +118,7 @@ public function __construct(
110118
$this->notifierInterface = $notifierInterface;
111119
$this->logger = $logger;
112120
$this->orderRegistrar = $orderRegistrar;
121+
$this->orderMutex = $orderMutex ?: ObjectManager::getInstance()->get(OrderMutexInterface::class);
113122
}
114123

115124
/**
@@ -140,7 +149,51 @@ public function execute(
140149
array $packages = [],
141150
\Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null
142151
) {
143-
$connection = $this->resourceConnection->getConnection('sales');
152+
return $this->orderMutex->execute(
153+
(int)$orderId,
154+
\Closure::fromCallable([$this, 'createShipment']),
155+
[
156+
$orderId,
157+
$items,
158+
$notify,
159+
$appendComment,
160+
$comment,
161+
$tracks,
162+
$packages,
163+
$arguments
164+
]
165+
);
166+
}
167+
168+
/**
169+
* Creates shipment for provided order ID
170+
*
171+
* @param int $orderId
172+
* @param \Magento\Sales\Api\Data\ShipmentItemCreationInterface[] $items
173+
* @param bool $notify
174+
* @param bool $appendComment
175+
* @param \Magento\Sales\Api\Data\ShipmentCommentCreationInterface|null $comment
176+
* @param \Magento\Sales\Api\Data\ShipmentTrackCreationInterface[] $tracks
177+
* @param \Magento\Sales\Api\Data\ShipmentPackageCreationInterface[] $packages
178+
* @param \Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface|null $arguments
179+
* @return int
180+
* @throws \Magento\Sales\Api\Exception\DocumentValidationExceptionInterface
181+
* @throws \Magento\Sales\Api\Exception\CouldNotShipExceptionInterface
182+
* @throws \Magento\Framework\Exception\InputException
183+
* @throws \Magento\Framework\Exception\NoSuchEntityException
184+
* @throws \DomainException
185+
* @SuppressWarnings(PHPMD.UnusedPrivateMethod)
186+
*/
187+
private function createShipment(
188+
$orderId,
189+
array $items = [],
190+
$notify = false,
191+
$appendComment = false,
192+
\Magento\Sales\Api\Data\ShipmentCommentCreationInterface $comment = null,
193+
array $tracks = [],
194+
array $packages = [],
195+
\Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface $arguments = null
196+
) {
144197
$order = $this->orderRepository->get($orderId);
145198
$shipment = $this->shipmentDocumentFactory->create(
146199
$order,
@@ -166,7 +219,6 @@ public function execute(
166219
__("Shipment Document Validation Error(s):\n" . implode("\n", $validationMessages->getMessages()))
167220
);
168221
}
169-
$connection->beginTransaction();
170222
try {
171223
$this->orderRegistrar->register($order, $shipment);
172224
$shipment = $this->shipmentRepository->save($shipment);
@@ -177,10 +229,8 @@ public function execute(
177229
$order->setStatus($this->config->getStateDefaultStatus($order->getState()));
178230
}
179231
$this->orderRepository->save($order);
180-
$connection->commit();
181232
} catch (\Exception $e) {
182233
$this->logger->critical($e);
183-
$connection->rollBack();
184234
throw new \Magento\Sales\Exception\CouldNotShipException(
185235
__('Could not save a shipment, see error log for details')
186236
);

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

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\Framework\App\ResourceConnection;
1111
use Magento\Framework\DB\Adapter\AdapterInterface;
12+
use Magento\Framework\DB\Select;
1213
use Magento\Sales\Api\CreditmemoRepositoryInterface;
1314
use Magento\Sales\Api\Data\CreditmemoCommentCreationInterface;
1415
use Magento\Sales\Api\Data\CreditmemoCreationArgumentsInterface;
@@ -26,6 +27,7 @@
2627
use Magento\Sales\Model\Order\OrderStateResolverInterface;
2728
use Magento\Sales\Model\Order\RefundAdapterInterface;
2829
use Magento\Sales\Model\Order\Validation\RefundOrderInterface;
30+
use Magento\Sales\Model\OrderMutex;
2931
use Magento\Sales\Model\RefundOrder;
3032
use Magento\Sales\Model\ValidatorResultInterface;
3133
use PHPUnit\Framework\MockObject\MockObject;
@@ -193,7 +195,8 @@ protected function setUp(): void
193195
$this->refundOrderValidatorMock,
194196
$this->notifierMock,
195197
$this->configMock,
196-
$this->loggerMock
198+
$this->loggerMock,
199+
new OrderMutex($this->resourceConnectionMock)
197200
);
198201
}
199202

@@ -208,10 +211,7 @@ protected function setUp(): void
208211
public function testOrderCreditmemo($orderId, $notify, $appendComment)
209212
{
210213
$items = [$this->creditmemoItemCreationMock];
211-
$this->resourceConnectionMock->expects($this->once())
212-
->method('getConnection')
213-
->with('sales')
214-
->willReturn($this->adapterInterface);
214+
$this->mockConnection($orderId);
215215
$this->orderRepositoryMock->expects($this->once())
216216
->method('get')
217217
->willReturn($this->orderMock);
@@ -304,7 +304,7 @@ public function testDocumentValidationException()
304304
$notify = true;
305305
$appendComment = true;
306306
$errorMessages = ['error1', 'error2'];
307-
307+
$this->mockConnection($orderId);
308308
$this->orderRepositoryMock->expects($this->once())
309309
->method('get')
310310
->willReturn($this->orderMock);
@@ -357,10 +357,7 @@ public function testCouldNotCreditmemoException()
357357
$items = [$this->creditmemoItemCreationMock];
358358
$notify = true;
359359
$appendComment = true;
360-
$this->resourceConnectionMock->expects($this->once())
361-
->method('getConnection')
362-
->with('sales')
363-
->willReturn($this->adapterInterface);
360+
$this->mockConnection($orderId);
364361
$this->orderRepositoryMock->expects($this->once())
365362
->method('get')
366363
->willReturn($this->orderMock);
@@ -419,4 +416,34 @@ public function dataProvider()
419416
'TestWithNotifyFalse' => [1, false, true],
420417
];
421418
}
419+
420+
/**
421+
* @param int $orderId
422+
*/
423+
private function mockConnection(int $orderId): void
424+
{
425+
$select = $this->createMock(Select::class);
426+
$select->expects($this->once())
427+
->method('from')
428+
->with('sales_order', 'entity_id')
429+
->willReturnSelf();
430+
$select->expects($this->once())
431+
->method('where')
432+
->with('entity_id = ?', $orderId)
433+
->willReturnSelf();
434+
$select->expects($this->once())
435+
->method('forUpdate')
436+
->with(true)
437+
->willReturnSelf();
438+
$this->adapterInterface->expects($this->once())
439+
->method('select')
440+
->willReturn($select);
441+
$this->resourceConnectionMock->expects($this->once())
442+
->method('getConnection')
443+
->with('sales')
444+
->willReturn($this->adapterInterface);
445+
$this->resourceConnectionMock->expects($this->once())
446+
->method('getTableName')
447+
->willReturnArgument(0);
448+
}
422449
}

0 commit comments

Comments
 (0)