Skip to content

Commit c63a78a

Browse files
authored
ENGCOM-7793: Fixing bug with non-existent customer group breaking quote #28902
2 parents 1bbcc11 + 820f557 commit c63a78a

File tree

3 files changed

+177
-1
lines changed

3 files changed

+177
-1
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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="OnePageCheckoutAsCustomerUsingNonExistentCustomerGroupTest">
12+
<annotations>
13+
<features value="OnePageCheckout"/>
14+
<stories value="OnePageCheckout within Offline Payment Methods"/>
15+
<title value="OnePageCheckout as a customer with non-existent customer group assigned to the quote"/>
16+
<description value="Checkout as a customer with non-existent customer group assigned to the quote"/>
17+
<severity value="AVERAGE"/>
18+
<testCaseId value="MC-36385"/>
19+
<group value="checkout"/>
20+
</annotations>
21+
<before>
22+
<!-- Create Simple Product -->
23+
<createData entity="SimpleProduct2" stepKey="createSimpleProduct">
24+
<field key="price">560</field>
25+
</createData>
26+
27+
<!-- Create customer group -->
28+
<createData entity="CustomCustomerGroup" stepKey="createCustomerGroup"/>
29+
30+
<!-- Create customer and assign it to the customer group created on the previous step -->
31+
<createData entity="Simple_US_Customer_Multiple_Addresses" stepKey="createCustomer">
32+
<field key="group_id">$$createCustomerGroup.id$$</field>
33+
</createData>
34+
</before>
35+
<after>
36+
<!-- Admin log out -->
37+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
38+
39+
<!-- Customer log out -->
40+
<actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/>
41+
42+
<!-- Delete created product -->
43+
<deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/>
44+
45+
<!-- Delete customer -->
46+
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
47+
</after>
48+
49+
<!-- Login as customer -->
50+
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin">
51+
<argument name="Customer" value="$$createCustomer$$"/>
52+
</actionGroup>
53+
54+
<!-- Add Simple Product to cart -->
55+
<amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToSimpleProductPage"/>
56+
<waitForPageLoad stepKey="waitForSimpleProductPageLoad"/>
57+
<actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage">
58+
<argument name="productName" value="$$createSimpleProduct.name$$"/>
59+
</actionGroup>
60+
61+
<!-- Delete customer group -->
62+
<deleteData createDataKey="createCustomerGroup" stepKey="deleteCustomerGroup"/>
63+
64+
<!-- Go to shopping cart -->
65+
<actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/>
66+
<actionGroup ref="FillShippingZipForm" stepKey="fillShippingZipForm">
67+
<argument name="address" value="US_Address_CA"/>
68+
</actionGroup>
69+
<click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="clickProceedToCheckout"/>
70+
<waitForPageLoad stepKey="waitForProceedToCheckout"/>
71+
72+
<!-- Check that error does not appear and shipping methods are available to select -->
73+
<dontSee selector="{{CheckoutCartMessageSection.errorMessage}}" userInput="No such entity with id = $$createCustomerGroup.id$$" stepKey="assertErrorMessage"/>
74+
<dontSee selector="{{CheckoutShippingMethodsSection.noQuotesMsg}}" userInput="Sorry, no quotes are available for this order at this time" stepKey="assertNoQuotesMessage"/>
75+
76+
<!-- Fill customer address data -->
77+
<waitForElementVisible selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="waitForShipHereVisible"/>
78+
<!-- Change address -->
79+
<click selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/>
80+
81+
<!-- Click next button to open payment section -->
82+
<click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/>
83+
<waitForPageLoad stepKey="waitForShipmentPageLoad"/>
84+
85+
<!-- Select payment solution -->
86+
<checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution" />
87+
88+
<!-- Check order summary in checkout -->
89+
<waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/>
90+
<click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/>
91+
<seeElement selector="{{CheckoutSuccessMainSection.success}}" stepKey="orderIsSuccessfullyPlaced"/>
92+
<grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/>
93+
94+
<!-- Login as admin -->
95+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
96+
97+
<!-- Open created order in backend -->
98+
<amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/>
99+
<waitForPageLoad stepKey="waitForOrdersPageLoad"/>
100+
<actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById">
101+
<argument name="orderId" value="$grabOrderNumber"/>
102+
</actionGroup>
103+
104+
<!-- Assert order total -->
105+
<scrollTo selector="{{AdminOrderTotalSection.grandTotal}}" stepKey="scrollToOrderTotalSection"/>
106+
<see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$565.00" stepKey="checkOrderTotalInBackend"/>
107+
108+
<!-- Assert order addresses -->
109+
<see selector="{{AdminShipmentAddressInformationSection.billingAddress}}" userInput="{{UK_Not_Default_Address.street[0]}}" stepKey="seeBillingAddressStreet"/>
110+
<see selector="{{AdminShipmentAddressInformationSection.billingAddress}}" userInput="{{UK_Not_Default_Address.city}}" stepKey="seeBillingAddressCity"/>
111+
<see selector="{{AdminShipmentAddressInformationSection.billingAddress}}" userInput="{{UK_Not_Default_Address.postcode}}" stepKey="seeBillingAddressPostcode"/>
112+
<see selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" userInput="{{UK_Not_Default_Address.street[0]}}" stepKey="seeShippingAddressStreet"/>
113+
<see selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" userInput="{{UK_Not_Default_Address.city}}" stepKey="seeShippingAddressCity"/>
114+
<see selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" userInput="{{UK_Not_Default_Address.postcode}}" stepKey="seeShippingAddressPostcode"/>
115+
</test>
116+
</tests>

app/code/Magento/Quote/Model/Quote.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Directory\Model\AllowedCountries;
1111
use Magento\Framework\Api\AttributeValueFactory;
1212
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
13+
use Magento\Framework\Exception\NoSuchEntityException;
1314
use Magento\Framework\Model\AbstractExtensibleModel;
1415
use Magento\Quote\Api\Data\PaymentInterface;
1516
use Magento\Quote\Model\Quote\Address;
@@ -1104,7 +1105,22 @@ public function getCustomerTaxClassId()
11041105
//if (!$this->getData('customer_group_id') && !$this->getData('customer_tax_class_id')) {
11051106
$groupId = $this->getCustomerGroupId();
11061107
if ($groupId !== null) {
1107-
$taxClassId = $this->groupRepository->getById($this->getCustomerGroupId())->getTaxClassId();
1108+
$taxClassId = null;
1109+
try {
1110+
$taxClassId = $this->groupRepository->getById($this->getCustomerGroupId())->getTaxClassId();
1111+
} catch (NoSuchEntityException $e) {
1112+
/**
1113+
* A customer MAY create a quote and AFTER that customer group MAY be deleted.
1114+
* That breaks a quote because it still refers no a non-existent customer group.
1115+
* In such a case we should load a new customer group id from the current customer
1116+
* object and use it to retrieve tax class and update quote.
1117+
*/
1118+
$groupId = $this->getCustomer()->getGroupId();
1119+
$this->setCustomerGroupId($groupId);
1120+
if ($groupId !== null) {
1121+
$taxClassId = $this->groupRepository->getById($groupId)->getTaxClassId();
1122+
}
1123+
}
11081124
$this->setCustomerTaxClassId($taxClassId);
11091125
}
11101126

app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
use Magento\Framework\DataObject\Copy;
3131
use Magento\Framework\DataObject\Factory;
3232
use Magento\Framework\Event\Manager;
33+
use Magento\Framework\Exception\NoSuchEntityException;
3334
use Magento\Framework\Model\Context;
35+
use Magento\Framework\Phrase;
3436
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
3537
use Magento\Quote\Api\Data\CartInterface;
3638
use Magento\Quote\Model\Quote;
@@ -640,6 +642,48 @@ public function testGetCustomerTaxClassId()
640642
$this->assertEquals($taxClassId, $result);
641643
}
642644

645+
/**
646+
* Test case when non-existent customer group is stored into the quote.
647+
* In such a case we should get a NoSuchEntityException exception and try
648+
* to get a valid customer group from the current customer object.
649+
*/
650+
public function testGetCustomerTaxClassIdForNonExistentCustomerGroup()
651+
{
652+
$customerId = 1;
653+
$nonExistentGroupId = 100;
654+
$groupId = 1;
655+
$taxClassId = 1;
656+
$groupMock = $this->getMockForAbstractClass(GroupInterface::class, [], '', false);
657+
$this->groupRepositoryMock->expects($this->at(0))
658+
->method('getById')
659+
->with($nonExistentGroupId)
660+
->willThrowException(new NoSuchEntityException(new Phrase('Entity Id does not exist')));
661+
$customerMock = $this->getMockForAbstractClass(
662+
CustomerInterface::class,
663+
[],
664+
'',
665+
false
666+
);
667+
$customerMock->expects($this->once())
668+
->method('getGroupId')
669+
->willReturn($groupId);
670+
$this->customerRepositoryMock->expects($this->once())
671+
->method('getById')
672+
->with($customerId)
673+
->willReturn($customerMock);
674+
$this->groupRepositoryMock->expects($this->at(1))
675+
->method('getById')
676+
->with($groupId)
677+
->willReturn($groupMock);
678+
$groupMock->expects($this->once())
679+
->method('getTaxClassId')
680+
->willReturn($taxClassId);
681+
$this->quote->setData('customer_id', $customerId);
682+
$this->quote->setData('customer_group_id', $nonExistentGroupId);
683+
$result = $this->quote->getCustomerTaxClassId();
684+
$this->assertEquals($taxClassId, $result);
685+
}
686+
643687
public function testGetAllAddresses()
644688
{
645689
$id = 1;

0 commit comments

Comments
 (0)