Skip to content

Commit 74ceb5a

Browse files
committed
MC-41945: Incorrect Tax Displayed for Virtual Products when Shipping and Billing are different
- Fix tax estimate for virtual quote randomly changes on checkout page
1 parent f121ac8 commit 74ceb5a

File tree

5 files changed

+154
-9
lines changed

5 files changed

+154
-9
lines changed

app/code/Magento/Checkout/view/frontend/web/js/model/checkout-data-resolver.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ define([
4545
resolveEstimationAddress: function () {
4646
var address;
4747

48-
if (checkoutData.getShippingAddressFromData()) {
49-
address = addressConverter.formAddressDataToQuoteAddress(checkoutData.getShippingAddressFromData());
50-
selectShippingAddress(address);
51-
} else {
52-
this.resolveShippingAddress();
53-
}
54-
5548
if (quote.isVirtual()) {
5649
if (checkoutData.getBillingAddressFromData()) {
5750
address = addressConverter.formAddressDataToQuoteAddress(
@@ -61,6 +54,11 @@ define([
6154
} else {
6255
this.resolveBillingAddress();
6356
}
57+
} else if (checkoutData.getShippingAddressFromData()) {
58+
address = addressConverter.formAddressDataToQuoteAddress(checkoutData.getShippingAddressFromData());
59+
selectShippingAddress(address);
60+
} else {
61+
this.resolveShippingAddress();
6462
}
6563
},
6664

app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php

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

77
namespace Magento\Tax\Model\Sales\Total\Quote;
88

9+
use Magento\Customer\Api\AccountManagementInterface as CustomerAccountManagement;
910
use Magento\Customer\Api\Data\AddressInterfaceFactory as CustomerAddressFactory;
1011
use Magento\Customer\Api\Data\AddressInterface as CustomerAddress;
1112
use Magento\Customer\Api\Data\RegionInterfaceFactory as CustomerAddressRegionFactory;
@@ -144,6 +145,11 @@ class CommonTaxCollector extends AbstractTotal
144145
*/
145146
private $quoteDetailsItemExtensionFactory;
146147

148+
/**
149+
* @var CustomerAccountManagement
150+
*/
151+
private $customerAccountManagement;
152+
147153
/**
148154
* Class constructor
149155
*
@@ -156,6 +162,8 @@ class CommonTaxCollector extends AbstractTotal
156162
* @param CustomerAddressRegionFactory $customerAddressRegionFactory
157163
* @param TaxHelper|null $taxHelper
158164
* @param QuoteDetailsItemExtensionInterfaceFactory|null $quoteDetailsItemExtensionInterfaceFactory
165+
* @param CustomerAccountManagement|null $customerAccountManagement
166+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
159167
*/
160168
public function __construct(
161169
\Magento\Tax\Model\Config $taxConfig,
@@ -166,7 +174,8 @@ public function __construct(
166174
CustomerAddressFactory $customerAddressFactory,
167175
CustomerAddressRegionFactory $customerAddressRegionFactory,
168176
TaxHelper $taxHelper = null,
169-
QuoteDetailsItemExtensionInterfaceFactory $quoteDetailsItemExtensionInterfaceFactory = null
177+
QuoteDetailsItemExtensionInterfaceFactory $quoteDetailsItemExtensionInterfaceFactory = null,
178+
?CustomerAccountManagement $customerAccountManagement = null
170179
) {
171180
$this->taxCalculationService = $taxCalculationService;
172181
$this->quoteDetailsDataObjectFactory = $quoteDetailsDataObjectFactory;
@@ -178,6 +187,8 @@ public function __construct(
178187
$this->taxHelper = $taxHelper ?: ObjectManager::getInstance()->get(TaxHelper::class);
179188
$this->quoteDetailsItemExtensionFactory = $quoteDetailsItemExtensionInterfaceFactory ?:
180189
ObjectManager::getInstance()->get(QuoteDetailsItemExtensionInterfaceFactory::class);
190+
$this->customerAccountManagement = $customerAccountManagement ??
191+
ObjectManager::getInstance()->get(CustomerAccountManagement::class);
181192
}
182193

183194
/**
@@ -411,7 +422,24 @@ public function mapItems(
411422
public function populateAddressData(QuoteDetailsInterface $quoteDetails, QuoteAddress $address)
412423
{
413424
$quoteDetails->setBillingAddress($this->mapAddress($address->getQuote()->getBillingAddress()));
414-
$quoteDetails->setShippingAddress($this->mapAddress($address));
425+
if ($address->getAddressType() === QuoteAddress::ADDRESS_TYPE_BILLING
426+
&& !$address->getCountryId()
427+
&& $address->getQuote()->isVirtual()
428+
&& $address->getQuote()->getCustomerId()
429+
) {
430+
$defaultBillingAddress = $this->customerAccountManagement->getDefaultBillingAddress(
431+
$address->getQuote()->getCustomerId()
432+
);
433+
$addressCopy = $address;
434+
if ($defaultBillingAddress) {
435+
$addressCopy = clone $address;
436+
$addressCopy->importCustomerAddressData($defaultBillingAddress);
437+
}
438+
439+
$quoteDetails->setShippingAddress($this->mapAddress($addressCopy));
440+
} else {
441+
$quoteDetails->setShippingAddress($this->mapAddress($address));
442+
}
415443
return $quoteDetails;
416444
}
417445

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminCreateTaxRuleWithTwoTaxRatesActionGroup" extends="AdminCreateTaxRuleActionGroup">
12+
<arguments>
13+
<argument name="taxRate2"/>
14+
</arguments>
15+
<click selector="{{AdminTaxRulesSection.selectTaxRate(taxRate2.code)}}" stepKey="selectTaxRate2" after="selectTaxRate"/>
16+
</actionGroup>
17+
</actionGroups>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
10+
<section name="StorefrontCustomerOrderViewSection">
11+
<element name="totalsTax" type="text" selector=".totals-tax-summary .amount .price" timeout="30"/>
12+
</section>
13+
</sections>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
10+
<test name="StorefrontCustomerWithDefaultBillingAddressAndCartWithVirtualProductTaxTest">
11+
<annotations>
12+
<features value="Tax"/>
13+
<stories value="Tax Calculation in Shopping Cart"/>
14+
<title value="Tax for quote with virtual products only should be calculated based on customer default billing address"/>
15+
<description value="Tax for quote with virtual products only should be calculated based on customer default billing address"/>
16+
<severity value="CRITICAL"/>
17+
<useCaseId value="MC-41945"/>
18+
<testCaseId value="MC-42650"/>
19+
<group value="Tax"/>
20+
</annotations>
21+
<before>
22+
<!-- Login to admin -->
23+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
24+
<!-- Fill in rules to display tax in the cart -->
25+
<actionGroup ref="EditTaxConfigurationByUIActionGroup" stepKey="fillDefaultTaxForms"/>
26+
<!-- Create tax rate for TX -->
27+
<createData entity="TaxRateTexas" stepKey="createTaxRateTX"/>
28+
<!-- Create tax rule -->
29+
<actionGroup ref="AdminCreateTaxRuleWithTwoTaxRatesActionGroup" stepKey="createTaxRule">
30+
<argument name="taxRate" value="$$createTaxRateTX$$"/>
31+
<argument name="taxRate2" value="US_NY_Rate_1"/>
32+
<argument name="taxRule" value="SimpleTaxRule"/>
33+
</actionGroup>
34+
<!-- Create a virtual product -->
35+
<createData entity="VirtualProduct" stepKey="createVirtualProduct"/>
36+
<!-- Create customer -->
37+
<createData entity="Simple_US_Customer_With_Different_Billing_Shipping_Addresses" stepKey="createCustomer"/>
38+
</before>
39+
<after>
40+
<!-- Ensure tax won't be shown in the cart -->
41+
<actionGroup ref="ChangeToDefaultTaxConfigurationUIActionGroup" stepKey="changeToDefaultTaxConfiguration"/>
42+
<!-- Delete tax rule -->
43+
<actionGroup ref="AdminDeleteTaxRule" stepKey="deleteTaxRule">
44+
<argument name="taxRuleCode" value="{{SimpleTaxRule.code}}" />
45+
</actionGroup>
46+
<!-- Delete tax rate for UK -->
47+
<deleteData createDataKey="createTaxRateTX" stepKey="deleteTaxRateUK"/>
48+
<!-- Delete virtual product -->
49+
<deleteData createDataKey="createVirtualProduct" stepKey="deleteVirtualProduct"/>
50+
<!-- Delete customer -->
51+
<deleteData createDataKey="createCustomer" stepKey="deleteCustomer"/>
52+
<!-- Logout from admin -->
53+
<actionGroup ref="AdminLogoutActionGroup" stepKey="amOnLogoutPage"/>
54+
</after>
55+
<!-- Login with created Customer -->
56+
<actionGroup ref="LoginToStorefrontActionGroup" stepKey="loginAsCustomer">
57+
<argument name="Customer" value="$$createCustomer$$"/>
58+
</actionGroup>
59+
<!-- Navigate to the product -->
60+
<actionGroup ref="StorefrontOpenProductEntityPageActionGroup" stepKey="openProduct2Page">
61+
<argument name="product" value="$$createVirtualProduct$$"/>
62+
</actionGroup>
63+
<!--Add to cart -->
64+
<actionGroup ref="StorefrontAddToTheCartActionGroup" stepKey="product2AddToCart"/>
65+
<!--Click on mini cart-->
66+
<actionGroup ref="StorefrontClickOnMiniCartActionGroup" stepKey="clickOnMiniCart"/>
67+
<!--Click on view and edit cart link-->
68+
<actionGroup ref="ClickViewAndEditCartFromMiniCartActionGroup" stepKey="goToShoppingCartFromMinicart"/>
69+
<waitForPageLoad stepKey="waitForViewAndEditCartToOpen"/>
70+
<waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/>
71+
<waitForElementVisible selector="{{CheckoutPaymentSection.tax}}" stepKey="waitForOverviewVisible1" />
72+
<!-- Verify tax in shopping cart -->
73+
<see selector="{{CheckoutPaymentSection.tax}}" userInput="$7.25" stepKey="verifyTaxInShoppingCartPage" />
74+
<!-- Navigate to payment page -->
75+
<actionGroup ref="StorefrontOpenCheckoutPageActionGroup" stepKey="goToCheckout"/>
76+
<waitForElementVisible selector="{{CheckoutPaymentSection.tax}}" stepKey="waitForOverviewVisible2"/>
77+
<!-- Verify tax on payment page -->
78+
<see selector="{{CheckoutPaymentSection.tax}}" userInput="$7.25" stepKey="verifyTaxOnPaymentPage"/>
79+
<!-- Place order -->
80+
<actionGroup ref="ClickPlaceOrderActionGroup" stepKey="clickPlacePurchaseOrder"/>
81+
<!-- Navigate to order details page -->
82+
<grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber22}}" stepKey="grabOrderNumber"/>
83+
<actionGroup ref="StorefrontOpenOrderFromSuccessPageActionGroup" stepKey="openOrderFromSuccessPage">
84+
<argument name="orderNumber" value="{$grabOrderNumber}"/>
85+
</actionGroup>
86+
<!-- Verify tax on order view page -->
87+
<see selector="{{StorefrontCustomerOrderViewSection.totalsTax}}" userInput="$7.25" stepKey="verifyTaxOnOrderViewPage"/>
88+
</test>
89+
</tests>

0 commit comments

Comments
 (0)