Skip to content

Commit f26c3dd

Browse files
committed
ACP2E-157: Coupon is marked used even if order doesn't create
- Fixed for a case when quote validation fails
1 parent 5734ca9 commit f26c3dd

File tree

3 files changed

+45
-17
lines changed

3 files changed

+45
-17
lines changed

app/code/Magento/SalesRule/Plugin/CouponUsagesIncrement.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Framework\Exception\NoSuchEntityException;
1111
use Magento\Quote\Model\Quote;
1212
use Magento\Quote\Model\QuoteManagement;
13+
use Magento\Sales\Api\Data\OrderInterface;
1314
use Magento\SalesRule\Model\Coupon\Quote\UpdateCouponUsages;
1415

1516
/**
@@ -34,19 +35,26 @@ public function __construct(UpdateCouponUsages $updateCouponUsages)
3435
* Increments number of coupon usages before placing order
3536
*
3637
* @param QuoteManagement $subject
38+
* @param \Closure $proceed
3739
* @param Quote $quote
3840
* @param array $orderData
39-
* @return void
40-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
41+
* @return OrderInterface|null
4142
* @throws NoSuchEntityException
43+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
4244
*/
43-
public function beforeSubmit(QuoteManagement $subject, Quote $quote, $orderData = [])
45+
public function aroundSubmit(QuoteManagement $subject, \Closure $proceed, Quote $quote, $orderData = [])
4446
{
4547
/* if coupon code has been canceled then need to notify the customer */
4648
if (!$quote->getCouponCode() && $quote->dataHasChangedFor('coupon_code')) {
4749
throw new NoSuchEntityException(__("The coupon code isn't valid. Verify the code and try again."));
4850
}
4951

5052
$this->updateCouponUsages->execute($quote, true);
53+
try {
54+
return $proceed($quote, $orderData);
55+
} catch (\Throwable $e) {
56+
$this->updateCouponUsages->execute($quote, false);
57+
throw $e;
58+
}
5159
}
5260
}

app/code/Magento/SalesRule/etc/events.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,4 @@
3939
<event name="sales_quote_collect_totals_before">
4040
<observer name="salesrule_sales_quote_collect_totals_before" instance="\Magento\SalesRule\Observer\QuoteResetAppliedRulesObserver" />
4141
</event>
42-
<event name="sales_model_service_quote_submit_failure">
43-
<observer name="sales_rule_decrement_coupon_usage_quote_submit_failure" instance="\Magento\SalesRule\Observer\CouponUsagesDecrement" />
44-
</event>
4542
</config>

dev/tests/integration/testsuite/Magento/SalesRule/Plugin/CouponUsagesTest.php

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Magento\Framework\ObjectManagerInterface;
1010
use Magento\Quote\Model\Quote;
1111
use Magento\Quote\Model\QuoteManagement;
12+
use Magento\Quote\Model\SubmitQuoteValidator;
1213
use Magento\Sales\Api\OrderManagementInterface;
1314
use Magento\Sales\Model\Service\OrderService;
1415
use Magento\SalesRule\Model\Coupon;
@@ -158,14 +159,16 @@ public function testSubmitQuoteAndCancelOrder()
158159
/**
159160
* Test to decrement coupon usages after exception on order placing
160161
*
162+
* @param array $mockObjects
161163
* @magentoDataFixture Magento/SalesRule/_files/coupons_limited_order.php
164+
* @magentoDbIsolation disabled
165+
* @dataProvider quoteSubmitFailureDataProvider
162166
*/
163-
public function testSubmitQuoteWithError()
167+
public function testQuoteSubmitFailure(array $mockObjects)
164168
{
165169
$customerId = 1;
166170
$couponCode = 'one_usage';
167171
$reservedOrderId = 'test01';
168-
$exceptionMessage = 'Some test exception';
169172

170173
/** @var Coupon $coupon */
171174
$coupon = $this->objectManager->get(Coupon::class);
@@ -174,23 +177,16 @@ public function testSubmitQuoteWithError()
174177
$quote = $this->objectManager->get(Quote::class);
175178
$quote->load($reservedOrderId, 'reserved_order_id');
176179

177-
/** @var OrderManagementInterface|MockObject $orderManagement */
178-
$orderManagement = $this->createMock(OrderManagementInterface::class);
179-
$orderManagement->expects($this->once())
180-
->method('place')
181-
->willThrowException(new \Exception($exceptionMessage));
182-
183180
/** @var QuoteManagement $quoteManagement */
184181
$quoteManagement = $this->objectManager->create(
185182
QuoteManagement::class,
186-
['orderManagement' => $orderManagement]
183+
$mockObjects
187184
);
188185

189186
try {
190187
$quoteManagement->submit($quote);
191188
} catch (\Exception $exception) {
192-
$this->assertEquals($exceptionMessage, $exception->getMessage());
193-
189+
sleep(10); // timeout to processing queue
194190
$this->usage->loadByCustomerCoupon($this->couponUsage, $customerId, $coupon->getId());
195191
$coupon->loadByCode($couponCode);
196192
self::assertEquals(
@@ -203,4 +199,31 @@ public function testSubmitQuoteWithError()
203199
);
204200
}
205201
}
202+
203+
/**
204+
* @return array
205+
*/
206+
public function quoteSubmitFailureDataProvider(): array
207+
{
208+
/** @var OrderManagementInterface|MockObject $orderManagement */
209+
$orderManagement = $this->createMock(OrderManagementInterface::class);
210+
$orderManagement->expects($this->once())
211+
->method('place')
212+
->willThrowException(new \Exception());
213+
214+
/** @var OrderManagementInterface|MockObject $orderManagement */
215+
$submitQuoteValidator = $this->createMock(SubmitQuoteValidator::class);
216+
$submitQuoteValidator->expects($this->once())
217+
->method('validateQuote')
218+
->willThrowException(new \Exception());
219+
220+
return [
221+
'order placing failure' => [
222+
['orderManagement' => $orderManagement]
223+
],
224+
'quote validation failure' => [
225+
['submitQuoteValidator' => $submitQuoteValidator]
226+
],
227+
];
228+
}
206229
}

0 commit comments

Comments
 (0)