Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing bug with non-existent customer group breaking quote #28902

Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->

<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
<test name="OnePageCheckoutAsCustomerUsingNonExistentCustomerGroupTest">
<annotations>
<features value="OnePageCheckout"/>
<stories value="OnePageCheckout within Offline Payment Methods"/>
<title value="OnePageCheckout as a customer with non-existent customer group assigned to the quote"/>
<description value="Checkout as a customer with non-existent customer group assigned to the quote"/>
<severity value="AVERAGE"/>
<testCaseId value="MC-36385"/>
<group value="checkout"/>
</annotations>
<before>
<!-- Create Simple Product -->
<createData entity="SimpleProduct2" stepKey="createSimpleProduct">
<field key="price">560</field>
</createData>

<!-- Create customer group -->
<createData entity="CustomCustomerGroup" stepKey="createCustomerGroup"/>

<!-- Create customer and assign it to the customer group created on the previous step -->
<createData entity="Simple_US_Customer_Multiple_Addresses" stepKey="createCustomer">
<field key="group_id">$$createCustomerGroup.id$$</field>
</createData>
</before>
<after>
<!-- Admin log out -->
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>

<!-- Customer log out -->
<actionGroup ref="StorefrontCustomerLogoutActionGroup" stepKey="customerLogout"/>

<!-- Delete created product -->
<deleteData createDataKey="createSimpleProduct" stepKey="deleteSimpleProduct"/>

<!-- Delete customer -->
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
</after>

<!-- Login as customer -->
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="customerLogin">
<argument name="Customer" value="$$createCustomer$$"/>
</actionGroup>

<!-- Add Simple Product to cart -->
<amOnPage url="{{StorefrontProductPage.url($$createSimpleProduct.custom_attributes[url_key]$$)}}" stepKey="navigateToSimpleProductPage"/>
<waitForPageLoad stepKey="waitForSimpleProductPageLoad"/>
<actionGroup ref="AddToCartFromStorefrontProductPageActionGroup" stepKey="addToCartFromStorefrontProductPage">
<argument name="productName" value="$$createSimpleProduct.name$$"/>
</actionGroup>

<!-- Delete customer group -->
<deleteData createDataKey="createCustomerGroup" stepKey="deleteCustomerGroup"/>

<!-- Go to shopping cart -->
<actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/>
<actionGroup ref="FillShippingZipForm" stepKey="fillShippingZipForm">
<argument name="address" value="US_Address_CA"/>
</actionGroup>
<click selector="{{CheckoutCartSummarySection.proceedToCheckout}}" stepKey="clickProceedToCheckout"/>
<waitForPageLoad stepKey="waitForProceedToCheckout"/>

<!-- Check that error does not appear and shipping methods are available to select -->
<dontSee selector="{{CheckoutCartMessageSection.errorMessage}}" userInput="No such entity with id = $$createCustomerGroup.id$$" stepKey="assertErrorMessage"/>
<dontSee selector="{{CheckoutShippingMethodsSection.noQuotesMsg}}" userInput="Sorry, no quotes are available for this order at this time" stepKey="assertNoQuotesMessage"/>

<!-- Fill customer address data -->
<waitForElementVisible selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="waitForShipHereVisible"/>
<!-- Change address -->
<click selector="{{CheckoutShippingSection.shipHereButton(UK_Not_Default_Address.street[0])}}" stepKey="clickShipHere"/>

<!-- Click next button to open payment section -->
<click selector="{{CheckoutShippingGuestInfoSection.next}}" stepKey="clickNext"/>
<waitForPageLoad stepKey="waitForShipmentPageLoad"/>

<!-- Select payment solution -->
<checkOption selector="{{CheckoutPaymentSection.billingAddressNotSameCheckbox}}" stepKey="selectPaymentSolution" />

<!-- Check order summary in checkout -->
<waitForElement selector="{{CheckoutPaymentSection.paymentSectionTitle}}" stepKey="waitForPaymentSectionLoaded"/>
<click selector="{{CheckoutPaymentSection.placeOrder}}" stepKey="clickPlaceOrderButton"/>
<seeElement selector="{{CheckoutSuccessMainSection.success}}" stepKey="orderIsSuccessfullyPlaced"/>
<grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/>

<!-- Login as admin -->
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>

<!-- Open created order in backend -->
<amOnPage url="{{AdminOrdersPage.url}}" stepKey="goToOrders"/>
<waitForPageLoad stepKey="waitForOrdersPageLoad"/>
<actionGroup ref="OpenOrderByIdActionGroup" stepKey="filterOrderGridById">
<argument name="orderId" value="$grabOrderNumber"/>
</actionGroup>

<!-- Assert order total -->
<scrollTo selector="{{AdminOrderTotalSection.grandTotal}}" stepKey="scrollToOrderTotalSection"/>
<see selector="{{AdminOrderTotalSection.grandTotal}}" userInput="$565.00" stepKey="checkOrderTotalInBackend"/>

<!-- Assert order addresses -->
<see selector="{{AdminShipmentAddressInformationSection.billingAddress}}" userInput="{{UK_Not_Default_Address.street[0]}}" stepKey="seeBillingAddressStreet"/>
<see selector="{{AdminShipmentAddressInformationSection.billingAddress}}" userInput="{{UK_Not_Default_Address.city}}" stepKey="seeBillingAddressCity"/>
<see selector="{{AdminShipmentAddressInformationSection.billingAddress}}" userInput="{{UK_Not_Default_Address.postcode}}" stepKey="seeBillingAddressPostcode"/>
<see selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" userInput="{{UK_Not_Default_Address.street[0]}}" stepKey="seeShippingAddressStreet"/>
<see selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" userInput="{{UK_Not_Default_Address.city}}" stepKey="seeShippingAddressCity"/>
<see selector="{{AdminShipmentAddressInformationSection.shippingAddress}}" userInput="{{UK_Not_Default_Address.postcode}}" stepKey="seeShippingAddressPostcode"/>
</test>
</tests>
18 changes: 17 additions & 1 deletion app/code/Magento/Quote/Model/Quote.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Magento\Directory\Model\AllowedCountries;
use Magento\Framework\Api\AttributeValueFactory;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Model\AbstractExtensibleModel;
use Magento\Quote\Api\Data\PaymentInterface;
use Magento\Quote\Model\Quote\Address;
Expand Down Expand Up @@ -1104,7 +1105,22 @@ public function getCustomerTaxClassId()
//if (!$this->getData('customer_group_id') && !$this->getData('customer_tax_class_id')) {
$groupId = $this->getCustomerGroupId();
if ($groupId !== null) {
$taxClassId = $this->groupRepository->getById($this->getCustomerGroupId())->getTaxClassId();
$taxClassId = null;
try {
$taxClassId = $this->groupRepository->getById($this->getCustomerGroupId())->getTaxClassId();
} catch (NoSuchEntityException $e) {
/**
* A customer MAY create a quote and AFTER that customer group MAY be deleted.
* That breaks a quote because it still refers no a non-existent customer group.
* In such a case we should load a new customer group id from the current customer
* object and use it to retrieve tax class and update quote.
*/
$groupId = $this->getCustomer()->getGroupId();
$this->setCustomerGroupId($groupId);
if ($groupId !== null) {
$taxClassId = $this->groupRepository->getById($groupId)->getTaxClassId();
}
}
$this->setCustomerTaxClassId($taxClassId);
}

Expand Down
44 changes: 44 additions & 0 deletions app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
use Magento\Framework\DataObject\Copy;
use Magento\Framework\DataObject\Factory;
use Magento\Framework\Event\Manager;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Model\Context;
use Magento\Framework\Phrase;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Quote\Model\Quote;
Expand Down Expand Up @@ -640,6 +642,48 @@ public function testGetCustomerTaxClassId()
$this->assertEquals($taxClassId, $result);
}

/**
* Test case when non-existent customer group is stored into the quote.
* In such a case we should get a NoSuchEntityException exception and try
* to get a valid customer group from the current customer object.
*/
public function testGetCustomerTaxClassIdForNonExistentCustomerGroup()
{
$customerId = 1;
$nonExistentGroupId = 100;
$groupId = 1;
$taxClassId = 1;
$groupMock = $this->getMockForAbstractClass(GroupInterface::class, [], '', false);
$this->groupRepositoryMock->expects($this->at(0))
->method('getById')
->with($nonExistentGroupId)
->willThrowException(new NoSuchEntityException(new Phrase('Entity Id does not exist')));
$customerMock = $this->getMockForAbstractClass(
CustomerInterface::class,
[],
'',
false
);
$customerMock->expects($this->once())
->method('getGroupId')
->willReturn($groupId);
$this->customerRepositoryMock->expects($this->once())
->method('getById')
->with($customerId)
->willReturn($customerMock);
$this->groupRepositoryMock->expects($this->at(1))
->method('getById')
->with($groupId)
->willReturn($groupMock);
$groupMock->expects($this->once())
->method('getTaxClassId')
->willReturn($taxClassId);
$this->quote->setData('customer_id', $customerId);
$this->quote->setData('customer_group_id', $nonExistentGroupId);
$result = $this->quote->getCustomerTaxClassId();
$this->assertEquals($taxClassId, $result);
}

public function testGetAllAddresses()
{
$id = 1;
Expand Down