magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.48k stars 9.29k forks source link

Incorrect Customer TAX Class saved with Quote when VAT Validation used on Guest orders #30018

Closed gwharton closed 3 years ago

gwharton commented 4 years ago

Preconditions (*)

  1. 2.4-develop core

Steps to reproduce (*)

- BACKEND

-- Catalog -> Products -> Add Product
--- Name = Test
--- Sku = TEST
--- Price = 100
--- Tax Class = Taxable Goods
--- Qty = 100
--- Save & Close

-- Stores -> Tax Zones and Rates -> Add New Tax Rate
--- Tax Identifier = Ireland Zero Rate
--- Zip Postcode = *
--- Country = Ireland 
--- Rate = 0
--- Save Rate

-- Stores -> Tax Rules -> Add New Tax Rule
--- Name = Ireland Zero Rate
--- Tax Rate = Ireland Zero Rate
--- Additional Settings
---- Add New Tax Class
----- Domestic
---- Add New Tax Class
----- VAT Error
---- Add New Tax Class
----- Invalid VAT
---- Add New Tax Class
----- Intra EU
--- Customer TAX Class = Intra EU (Deselect all others)
--- Save

-- Customers -> Customer Group -> Add New Customer Group
--- Group Name = Domestic
--- Tax Class = Domestic
--- Save Customer Group

-- Customers -> Customer Group -> Add New Customer Group
--- Group Name = Invalid VAT
--- Tax Class = Invalid VAT
--- Save Customer Group

-- Customers -> Customer Group -> Add New Customer Group
--- Group Name = VAT Error
--- Tax Class = VAT Error
--- Save Customer Group

-- Customers -> Customer Group -> Add New Customer Group
--- Group Name = Intra EU
--- Tax Class = Intra EU
--- Save Customer Group

-- Store -> Configuration -> Customers -> Customer Configuration -> Create new account options
--- Enable Automatic Assignment to Customer Group = Yes
--- Tax Calculation Based On = Shipping Address
--- Group for Valid VAT ID - Domestic = Domestic
--- Group for Valid VAT ID - Intra-Union = Intra EU
--- Group for Invalid VAT ID = Invalid VAT
--- Validation Error Group = VAT Error
--- Validate on Each Transaction = Yes
--- Show VAT Number on Storefront = Yes
--- Save Config

-- Store -> Configuration -> Customers -> Customer Configuration -> Name and Address Options
--- Show Tax/VAT Number = Optional
--- Save Config

-- Store -> Configuration -> General -> General -> Store Information
--- Country = United Kingdom
--- VAT Number = GB782325424 (This is ebay UK's vat number)
--- Validate VAT Number
--- Save Config

- FRONTEND

-- go to /test.html
-- Add 1 item to cart

- MYSQL

-- Review tax_class table and familiarise yourself with tax class id's and group names
-- Inspect quote table and check customer_tax_class_id field of new quote item. 
-- It should match to "Retail Customer" Group.

- FRONTEND

-- Minicart -> Proceed to checkout
-- Email = test@test.com
-- First Name = Test
-- Last Name = Test
-- Street Address = Test
-- Country = Ireland
-- City = Test
-- Phone Number = 12345
-- VAT Number = IE3206488LH (This is Stripe IE's VAT Number)
-- Next
-- Wait for payment Page to show

- MYSQL
-- Inspect quote table and check customer_tax_class_id field of quote item. 
-- It should match to "Intra-EU" Group.

- FRONTEND
-- Place Order

- MYSQL
-- Inspect quote table and check customer_tax_class_id field of quote item. 
-- It should match to "Intra-EU" Group. It is not. It has changed back to "Retail Customer"

Expected result (*)

  1. I expect the quote item corresponding to the order to have the correctly assigned Customer Tax Class of "Intra-EU" after the order is placed

Actual result (*)

  1. The Customer Tax Class is set to Intra-EU at the quote stage, but is overwritten with "Retail Customer" once the order is placed.

Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.

m2-assistant[bot] commented 4 years ago

Hi @gwharton. Thank you for your report. To help us process this issue please make sure that you provided the following information:

Please make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, please, add a comment to the issue:

@magento give me 2.4-develop instance - upcoming 2.4.x release

For more details, please, review the Magento Contributor Assistant documentation.

Please, add a comment to assign the issue: @magento I am working on this


:clock10: You can find the schedule on the Magento Community Calendar page.

:telephone_receiver: The triage of issues happens in the queue order. If you want to speed up the delivery of your contribution, please join the Community Contributions Triage session to discuss the appropriate ticket.

:movie_camera: You can find the recording of the previous Community Contributions Triage on the Magento Youtube Channel

:pencil2: Feel free to post questions/proposals/feedback related to the Community Contributions Triage process to the corresponding Slack Channel

m2-assistant[bot] commented 4 years ago

Hi @engcom-Oscar. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:

engcom-Oscar commented 4 years ago

Hi @gwharton , thank you for your report. I have checked this issue and it reproducing even without MSI modules, on vanila 2.4-develop branch of Magento. This why I have removed MSI from description, then we could proceed to work with it on our repository.

magento-engcom-team commented 4 years ago

:white_check_mark: Confirmed by @engcom-Oscar Thank you for verifying the issue. Based on the provided information internal tickets MC-37666 were created

Issue Available: @engcom-Oscar, You will be automatically unassigned. Contributors/Maintainers can claim this issue to continue. To reclaim and continue work, reassign the ticket to yourself.

gwharton commented 4 years ago

Well, it took me about 7 hours to get to the bottom of this one.

Magento\Sales\Observer\Frontend\RestoreCustomerGroupId is fired by the event sales_quote_address_collect_totals_after

This is called numerous times throughout the checkout process.

It looks as if this plugin checks if the setting for "Tax Calculation Based On" is set to "Shipping Address", and if the Customer Group Id of the quote has previously changed (indicating that the group has changed due to VAT validation) then the change in Group ID is reverted.

I have no idea why, but this seems intentional. VAT should be calculated based on where the goods are being delivered to, not the billing address, so it seems odd to kill the updated Group ID, and hence the Customer Tax Class ID in this case.

If the Group ID is not set correctly, then the quote->getCustomerTaxClassId function will not work, as it generates the tax class in real time from the group ID.

This needs some thought.

gwharton commented 4 years ago

https://github.com/magento/magento2/blob/7ddd47e87e217ba20b883e9ee22e5e3ef618e6df/app/code/Magento/Quote/Model/QuoteManagement.php#L399

Also needs addressing if you want to keep the adjusted customer group in the quote object and order object after VAT validation for guest orders.

sdzhepa commented 3 years ago

The issue has been fixed by Magento team and delivered with internal PR in the scope of MC-37666 Related commits https://github.com/magento/magento2/search?q=MC-37666&type=commits

gwharton commented 3 years ago

@sdzhepa, This doesn't fix the problem for me.

Problem 1

The "sales_customer_validate_vat_number" event is fired on the frontend, and also webapi when VAT validation is carried out.

The following observer subscribes to that event. "Magento\Sales\Observer\Frontend\RestoreCustomerGroupId"

That Observer removes any changes to the quote->CustomerGroupId field which were made by the VAT Validation routines.

I guess this event is not triggered by the unit test as the VAT validation object is mocked, and never fires this event.

With these events in place, when the order is placed, the Observer resets the customer group in the quote to 0, which is then copied forwards into the $order object.

Problem 2

The fix put in place

https://github.com/magento/magento2/blob/544296e3172e9343e1c87a8502220dff64efa89b/app/code/Magento/Quote/Model/QuoteManagement.php#L400-L401

If it is a guest order, then doesn't $quote->getCustomer() return an empty customer object

https://github.com/magento/magento2/blob/544296e3172e9343e1c87a8502220dff64efa89b/app/code/Magento/Quote/Model/Quote.php#L1014-L1029

and would just result in the fix setting the $quote->setCustomerGroupId() call with null parameter.

My Workaround

Stop the overwriting of the CustomerGroupId in the quote object on VAT validation. I have no idea why this is put in, in the first place. Seems incorrect for it to be there.

etc/frontend/events.xml etc/webapi_rest/events.xml etc/webapi_soap/events.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_quote_address_collect_totals_after">
        <observer name="sales_customer_validate_vat_number" disabled="true" />
    </event>
</config>

Stop the overwriting of the CustomerGroupId in the quote object on order placement

--- Model/QuoteManagement.orig.php  2020-09-19 18:09:21.263000000 +0100
+++ Model/QuoteManagement.php   2020-09-19 18:09:25.540000000 +0100
@@ -395,7 +395,6 @@
                 }
             }
             $quote->setCustomerIsGuest(true);
-            $quote->setCustomerGroupId(\Magento\Customer\Api\Data\GroupInterface::NOT_LOGGED_IN_ID);
         }

         $remoteAddress = $this->remoteAddress->getRemoteAddress();
kanevbg commented 1 year ago

status?