Skip to content

Commit 707da04

Browse files
committed
ACP2E-690: Discount code Times Used is being counted twice
1 parent ef0ffcd commit 707da04

File tree

4 files changed

+169
-1
lines changed

4 files changed

+169
-1
lines changed

app/code/Magento/SalesRule/Model/Coupon/UpdateCouponUsages.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ public function execute(OrderInterface $subject, bool $increment): OrderInterfac
5959
$updateInfo->setCustomerId((int)$subject->getCustomerId());
6060
$updateInfo->setIsIncrement($increment);
6161

62+
if ($subject->getOrigData('customer_id') === null
63+
&& $subject->getOrigData('coupon_code') !== null
64+
&& $subject->getOrigData('customer_id') !== $subject->getData('customer_id')) {
65+
$updateInfo->setCouponAlreadyApplied(true);
66+
}
67+
6268
$this->couponUsageProcessor->process($updateInfo);
6369

6470
return $subject;

app/code/Magento/SalesRule/Model/Coupon/Usage/Processor.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ private function updateCouponUsages(UpdateInfo $updateInfo): void
9393
$isIncrement = $updateInfo->isIncrement();
9494
$this->coupon->load($updateInfo->getCouponCode(), 'code');
9595
if ($this->coupon->getId()) {
96-
if ($updateInfo->isIncrement() || $this->coupon->getTimesUsed() > 0) {
96+
if (!$updateInfo->isCouponAlreadyApplied()
97+
&& ($updateInfo->isIncrement() || $this->coupon->getTimesUsed() > 0)) {
9798
$this->coupon->setTimesUsed($this->coupon->getTimesUsed() + ($isIncrement ? 1 : -1));
9899
$this->coupon->save();
99100
}

app/code/Magento/SalesRule/Model/Coupon/Usage/UpdateInfo.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class UpdateInfo extends DataObject
1818
private const COUPON_CODE_KEY = 'coupon_code';
1919
private const CUSTOMER_ID_KEY = 'customer_id';
2020
private const IS_INCREMENT_KEY = 'is_increment';
21+
private const IS_COUPON_ALREADY_APPLIED = 'is_coupon_already_applied';
2122

2223
/**
2324
* Get applied rule ids
@@ -104,4 +105,26 @@ public function setIsIncrement(bool $value): void
104105
{
105106
$this->setData(self::IS_INCREMENT_KEY, $value);
106107
}
108+
109+
/**
110+
* Check if coupon already used
111+
*
112+
* @return bool
113+
*/
114+
public function isCouponAlreadyApplied(): bool
115+
{
116+
return $this->getData(self::IS_COUPON_ALREADY_APPLIED) !== false
117+
&& (bool)$this->getData(self::IS_COUPON_ALREADY_APPLIED);
118+
}
119+
120+
/**
121+
* Set if coupon already used for
122+
*
123+
* @param bool $value
124+
* @return void
125+
*/
126+
public function setCouponAlreadyApplied(bool $value): void
127+
{
128+
$this->setData(self::IS_COUPON_ALREADY_APPLIED, $value);
129+
}
107130
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminCouponCodeCheckTimesUsedAfterGuestOrderTest">
12+
<annotations>
13+
<features value="SalesRule"/>
14+
<stories value="Discount code `Times Used` is being counted twice while Customer account created just after order placed by converting guest details in tandem."/>
15+
<title value="Discount code Times Used is being counted twice when customer account got created via the `Create Account` link just after placing an order."/>
16+
<description value="Discount code `Times Used` is being counted twice while Customer account created just after order placed by converting guest details in tandem."/>
17+
<severity value="AVERAGE"/>
18+
<testCaseId value="AC-2843"/>
19+
<useCaseId value="ACP2E-690"/>
20+
<group value="salesRule"/>
21+
</annotations>
22+
23+
<before>
24+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
25+
<!--Create simple product-->
26+
<createData entity="SimpleProduct2" stepKey="createSimpleProduct"/>
27+
</before>
28+
<after>
29+
<!--Delete simple product created during the test-->
30+
<deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/>
31+
<!--Delete the cart price rule we made during the test-->
32+
<actionGroup ref="DeleteCartPriceRuleByName" stepKey="cleanUpRule">
33+
<argument name="ruleName" value="{{CatPriceRule.name}}"/>
34+
</actionGroup>
35+
<!--Delete customer created during the test-->
36+
<actionGroup ref="DeleteCustomerByEmailActionGroup" stepKey="deleteCustomer">
37+
<argument name="email" value="{{CustomerEntityOne.email}}"/>
38+
</actionGroup>
39+
<actionGroup ref="AdminLogoutActionGroup" stepKey="adminLogout"/>
40+
</after>
41+
42+
<!--Go to admin Marketing > Cart Price Rule Page-->
43+
<actionGroup ref="AdminOpenCartPriceRulesPageActionGroup" stepKey="amOnCartPriceList"/>
44+
45+
<!--Create a new rule with specified details below-->
46+
<click selector="{{AdminCartPriceRulesSection.addNewRuleButton}}" stepKey="clickAddNewRule" after="amOnCartPriceList"/>
47+
<fillField selector="{{AdminCartPriceRulesFormSection.ruleName}}" userInput="{{CatPriceRule.name}}" stepKey="fillRuleName" after="clickAddNewRule"/>
48+
<selectOption selector="{{AdminCartPriceRulesFormSection.websites}}" userInput="{{CartPriceRuleConditionAndFreeShippingApplied.websites}}" stepKey="selectWebsites"/>
49+
<selectOption selector="{{AdminCartPriceRulesFormSection.customerGroups}}" parameterArray="[{{CatPriceRule.customerGroups}}]" stepKey="selectCustomerGroup"/>
50+
51+
<!-- Choose coupon type specific coupon and tick auto generation checkbox -->
52+
<selectOption selector="{{AdminCartPriceRulesFormSection.coupon}}" userInput="{{CatPriceRule.coupon_type}}" stepKey="selectCouponType"/>
53+
<checkOption selector="{{AdminCartPriceRulesFormSection.useAutoGeneration}}" stepKey="tickAutoGeneration"/>
54+
<fillField selector="{{AdminCartPriceRulesFormSection.userPerCustomer}}" userInput="1" stepKey="fillUsesPerCustomer"/>
55+
56+
<!--Navigate to Actions tab and set the specified details-->
57+
<click selector="{{AdminCartPriceRulesFormSection.actionsHeader}}" stepKey="clickToExpandActions" after="fillUsesPerCustomer"/>
58+
<selectOption selector="{{AdminCartPriceRulesFormSection.apply}}" userInput="{{CatPriceRule.apply}}" stepKey="selectActionType"/>
59+
<fillField selector="{{AdminCartPriceRulesFormSection.discountAmount}}" userInput="{{CatPriceRule.discountAmount}}" stepKey="fillDiscountAmount"/>
60+
<click selector="{{AdminCartPriceRulesFormSection.saveAndContinue}}" stepKey="clickSaveAndContinueButton"/>
61+
<waitForPageLoad stepKey="waitForPageToLoad"/>
62+
63+
<!-- Navigate to Manage Coupon Codes section to generate 5 coupon code -->
64+
<click selector="{{AdminCartPriceRulesFormSection.manageCouponCodesHeader}}" stepKey="expandCouponSection" after="clickSaveAndContinueButton"/>
65+
<fillField selector="{{AdminCartPriceRulesFormSection.couponQty}}" userInput="5" stepKey="fillCouponQty"/>
66+
<click selector="{{AdminCartPriceRulesFormSection.generateCouponsButton}}" stepKey="clickGenerate"/>
67+
<see selector="{{AdminCartPriceRulesFormSection.successMessage}}" userInput="Message is added to queue, wait to get your coupons soon" stepKey="seeGenerationSuccess"/>
68+
69+
<!--Start coupon code generator queue-->
70+
<actionGroup ref="CliConsumerStartActionGroup" stepKey="startMessageQueue">
71+
<argument name="consumerName" value="{{AdminCodeGeneratorMessageConsumerData.consumerName}}"/>
72+
<argument name="maxMessages" value="5"/>
73+
</actionGroup>
74+
75+
<!--Reload cart price rule page-->
76+
<actionGroup ref="ReloadPageActionGroup" stepKey="refreshPage" after="startMessageQueue"/>
77+
78+
<!--Open Manage Coupon Codes tab again to see generated coupon codes-->
79+
<click selector="{{AdminCartPriceRulesFormSection.manageCouponCodesHeader}}" stepKey="expandCouponSectionSecondTime" after="refreshPage"/>
80+
<scrollTo selector="{{AdminCartPriceRulesFormSection.couponGridUsedHeader}}" stepKey="scrollToCouponGridUsedHeader" after="expandCouponSectionSecondTime"/>
81+
<waitForElementVisible selector="{{AdminCartPriceRulesFormSection.couponGridUsedHeader}}" stepKey="waitForNewRule" after="scrollToCouponGridUsedHeader"/>
82+
83+
<!--Assert coupon codes grid header is correct -->
84+
<see selector="{{AdminCartPriceRulesFormSection.couponGridUsedHeader}}" userInput="Used" stepKey="seeCorrectUsedHeader" after="waitForNewRule"/>
85+
86+
<!--Grab a coupon code and hold on to it for later -->
87+
<grabTextFrom selector="{{AdminCartPriceRulesFormSection.generatedCouponByIndex('1')}}" stepKey="couponCode"/>
88+
89+
90+
<!--Open the Product Page, add the product to Cart, go to Shopping Cart and Apply the same coupon code -->
91+
<amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="openProductPage" after="couponCode"/>
92+
<actionGroup ref="ApplyCartRuleOnStorefrontActionGroup" stepKey="applyCartPriceRule">
93+
<argument name="product" value="$$createSimpleProduct$$"/>
94+
<argument name="couponCode" value="{$couponCode}"/>
95+
</actionGroup>
96+
<waitForText userInput='You used coupon code "{$couponCode}"' stepKey="waitForText"/>
97+
<see selector="{{StorefrontMessagesSection.success}}" userInput='You used coupon code "{$couponCode}"' stepKey="seeSuccessMessage"/>
98+
99+
<!--Proceed to checkout for guest customer details-->
100+
<actionGroup ref="StorefrontClickProceedToCheckoutActionGroup" stepKey="clickProceedToCheckout"/>
101+
<actionGroup ref="GuestCheckoutFillingShippingSectionActionGroup" stepKey="guestCheckoutFillingShippingSection">
102+
<argument name="customerVar" value="CustomerEntityOne"/>
103+
<argument name="customerAddressVar" value="CustomerAddressSimple"/>
104+
</actionGroup>
105+
<actionGroup ref="CheckBillingAddressInCheckoutActionGroup" stepKey="guestSeeAddress">
106+
<argument name="customerVar" value="CustomerEntityOne"/>
107+
<argument name="customerAddressVar" value="CustomerAddressSimple"/>
108+
</actionGroup>
109+
<actionGroup ref="CheckoutPlaceOrderActionGroup" stepKey="guestPlaceOrder">
110+
<argument name="orderNumberMessage" value="CONST.successGuestCheckoutOrderNumberMessage"/>
111+
<argument name="emailYouMessage" value="CONST.successCheckoutEmailYouMessage"/>
112+
</actionGroup>
113+
114+
<!-- Create Customer using guest details while placing an order -->
115+
<actionGroup ref="StorefrontRegisterCustomerFromOrderSuccessPage" stepKey="createCustomerAfterPlaceOrder" after="guestPlaceOrder">
116+
<argument name="customer" value="CustomerEntityOne"/>
117+
</actionGroup>
118+
119+
<!-- Run cron three times to force update and wait 2 minutes -->
120+
<!-- Run cron -->
121+
<magentoCron stepKey="runAllCronJobs"/>
122+
<reloadPage stepKey="refreshPageAfterCronRun"/>
123+
124+
<!-- Search and go to cart price rule page again -->
125+
<amOnPage url="{{AdminCartPriceRulesPage.url}}" stepKey="amOnCartPriceListSecondTime" after="refreshPageAfterCronRun"/>
126+
<waitForPageLoad stepKey="waitForPriceList"/>
127+
<fillField selector="{{AdminCartPriceRulesSection.filterByNameInput}}" userInput="{{CatPriceRule.name}}" stepKey="filterByName"/>
128+
<click selector="{{AdminCartPriceRulesSection.searchButton}}" stepKey="doFilter"/>
129+
<click selector="{{AdminCartPriceRulesSection.rowByIndex('1')}}" stepKey="goToEditRulePage"/>
130+
<click selector="{{AdminCartPriceRulesFormSection.manageCouponCodesHeader}}" stepKey="expandCouponSectionThirdTime" after="goToEditRulePage"/>
131+
<scrollTo selector="{{AdminCartPriceRulesFormSection.couponGridUsedHeader}}" stepKey="scrollToCouponGridUsedHeaderSecondTime" after="expandCouponSectionThirdTime"/>
132+
<waitForElementVisible selector="{{AdminCartPriceRulesFormSection.couponGridUsedHeader}}" stepKey="waitForCouponGridToLoad" after="scrollToCouponGridUsedHeaderSecondTime"/>
133+
134+
<!--Verify coupon does not used twice-->
135+
<see userInput="1" selector="{{AdminCartPriceRulesFormSection.generatedCouponTimesUsed('1')}}" stepKey="seeTimesUsed"/>
136+
<wait time="5" stepKey="waitToSeeTimesUsed" after="seeTimesUsed"/>
137+
</test>
138+
</tests>

0 commit comments

Comments
 (0)