Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix: Handle taxes for local pickup shipping #6631

Merged
merged 1 commit into from Jun 27, 2022
Merged

Conversation

senadir
Copy link
Member

@senadir senadir commented Jun 26, 2022

This PR fixes an issue in which taxes are calculated against the user address for local pickups orders. A niche issue, but an important one.

Fixes #6480

Why did this issue happen in Store API

Shortcode Checkout has a function called process_checkout that handles submitting an order, that functions passes $_POST data around, it also creates an order just when you finish an order. Store API can't that function, because we can't support $_POST via a rest api, and because we create an order early on.

For this purpose, Store API has its own process_checkout function, the get_route_post_response function of /checkout route.

WooCommerce Shortcode also calculates the order totals using wc()->cart->calculate_totals it then copies that result to the created order.

Store API augments the order with all correct informations, than calls WC_Order::calculate_totals.

The issue here is that those two functions are slightly different, exactly around how they calculate taxes.

The cart version decides on what address it should calculate taxes using the WC_Customer::get_taxable_address function.

The order version uses WC_Abstract_Order::get_tax_location.

The problem stems from the fact that WC_Customer::get_taxable_address checks if the cart has local pickup selected (in which it defaults to base location), but WC_Abstract_Order::get_tax_location doesn't do any of that, and just checks the value of woocommerce_tax_based_on setting.

This is a long standing issue, that is simply hard to discover because most Checkout block users. who have local pickup probably have their customers locations in the same place as the shop, so the taxes are the same.

Good news is that @iamdharmesh discovered the same issue from WooCommerce Admin side and fixed the issue in WooCommerce core woocommerce/woocommerce#33330, the fix will land in WooCommerce Core 6.8.0 which is still 3 months away for us (we do L-1 for WC core when we can).

This PR does a workaround by calling WC_Customer::get_taxable_address instead, and we should remove it once WC Core 6.8.0 is the min version.

Testing

User Facing Testing

  1. Set store address to 123 Test Street, 90210 Beverly Hills, CA, USA
  2. Enable taxes
  3. Add a "Standard" tax rates in US, CA. Set it to: 10%
  4. Add the following shipping methods: "Flat rate" for $10 and "Local pickup" for free.
  5. Add a payment option (e.g., Cash on delivery).
  6. Add a physical product to the cart.
  7. Use an outside state address on the front-end. (e.g., 60 29th Street #343, 35005 birmingham, AL, USA)
  8. Go to the Cart block and select the Local pickup shipping method. Check that we have a tax of 10% applied.
  9. Go to the Checkout block and select the Local pickup shipping method. Check that we have a tax of 10% applied.
  10. Place your order. Check on the Order received page that the displayed tax is actually added to the total.
  11. Go to Edit Order. Check that taxes were applied correctly there as well.
  12. On Checkout again, select flat rate, using the same external address, and make sure taxes are not applied.

Changelog

Fix: Correctly calculacte taxes for local pickups.

@senadir senadir self-assigned this Jun 26, 2022
@rubikuserbot rubikuserbot requested review from a team and nielslange and removed request for a team June 26, 2022 22:18
@senadir senadir added type: bug The issue/PR concerns a confirmed bug. status: blocker Used on issues or pulls that block work from being released. block: checkout Issues related to the checkout block. labels Jun 26, 2022
@github-actions
Copy link
Contributor

Remove custom local pickup handling once WooCommerce 6.8....

Remove custom local pickup handling once WooCommerce 6.8.0 is the minimum version.


* @todo: Remove custom local pickup handling once WooCommerce 6.8.0 is the minimum version.
*
* @param array $location Taxes location.
* @return array updated location that accounts for local pickup.
*/
public function handle_local_pickup_taxes( $location ) {
$customer = wc()->customer;
if ( ! empty( $customer ) ) {
return $customer->get_taxable_address();
}
return $location;

🚀 This comment was generated by the automations bot based on a todo comment in 56e4b9a in #6631. cc @senadir

@senadir senadir added this to the 8.0.0 milestone Jun 26, 2022
@@ -44,6 +44,9 @@ public function create_order_from_cart() {
* @param \WC_Order $order The order object to update.
*/
public function update_order_from_cart( \WC_Order $order ) {
// Ensures Local pickups are accounted for.
add_filter( 'woocommerce_order_get_tax_location', array( $this, 'handle_local_pickup_taxes' ) );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to limit where we call this logic, this function matters because this is where we call calculate_totals.

Comment on lines +440 to +456
/**
* Passes the correct base for local pick orders
*
* @todo: Remove custom local pickup handling once WooCommerce 6.8.0 is the minimum version.
*
* @param array $location Taxes location.
* @return array updated location that accounts for local pickup.
*/
public function handle_local_pickup_taxes( $location ) {
$customer = wc()->customer;

if ( ! empty( $customer ) ) {
return $customer->get_taxable_address();
}

return $location;
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_tax_location has a filter in which we're using. In this case, we check if we have a user (we always do at the submit point) and get the address from there (which accounts for local pickup).

@github-actions
Copy link
Contributor

Size Change: 0 B

Total Size: 874 kB

ℹ️ View Unchanged
Filename Size
build/active-filters-frontend.js 7.26 kB
build/active-filters.js 7.92 kB
build/all-products-frontend.js 18.1 kB
build/all-products.js 33.5 kB
build/all-reviews.js 7.79 kB
build/attribute-filter-frontend.js 25 kB
build/attribute-filter.js 14.2 kB
build/blocks-checkout.js 17.4 kB
build/cart-blocks/cart-accepted-payment-methods-frontend.js 1.16 kB
build/cart-blocks/cart-express-payment-frontend.js 5.06 kB
build/cart-blocks/cart-items-frontend.js 299 B
build/cart-blocks/cart-line-items--mini-cart-contents-block/products-table-frontend.js 5.27 kB
build/cart-blocks/cart-line-items-frontend.js 432 B
build/cart-blocks/cart-order-summary-frontend.js 1.11 kB
build/cart-blocks/cart-totals-frontend.js 321 B
build/cart-blocks/empty-cart-frontend.js 345 B
build/cart-blocks/filled-cart-frontend.js 782 B
build/cart-blocks/order-summary-coupon-form-frontend.js 2.62 kB
build/cart-blocks/order-summary-discount-frontend.js 2.12 kB
build/cart-blocks/order-summary-fee-frontend.js 274 B
build/cart-blocks/order-summary-heading-frontend.js 454 B
build/cart-blocks/order-summary-shipping--checkout-blocks/order-summary-shipping-frontend.js 6.35 kB
build/cart-blocks/order-summary-shipping-frontend.js 427 B
build/cart-blocks/order-summary-subtotal-frontend.js 274 B
build/cart-blocks/order-summary-taxes-frontend.js 432 B
build/cart-blocks/proceed-to-checkout-frontend.js 1.15 kB
build/cart-frontend.js 45.6 kB
build/cart.js 44.2 kB
build/checkout-blocks/actions-frontend.js 1.41 kB
build/checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 4.12 kB
build/checkout-blocks/billing-address-frontend.js 888 B
build/checkout-blocks/contact-information-frontend.js 2.83 kB
build/checkout-blocks/express-payment-frontend.js 5.36 kB
build/checkout-blocks/fields-frontend.js 345 B
build/checkout-blocks/order-note-frontend.js 1.08 kB
build/checkout-blocks/order-summary-cart-items-frontend.js 3.66 kB
build/checkout-blocks/order-summary-coupon-form-frontend.js 2.78 kB
build/checkout-blocks/order-summary-discount-frontend.js 2.25 kB
build/checkout-blocks/order-summary-fee-frontend.js 275 B
build/checkout-blocks/order-summary-frontend.js 1.11 kB
build/checkout-blocks/order-summary-shipping-frontend.js 603 B
build/checkout-blocks/order-summary-subtotal-frontend.js 274 B
build/checkout-blocks/order-summary-taxes-frontend.js 432 B
build/checkout-blocks/payment-frontend.js 7.67 kB
build/checkout-blocks/shipping-address-frontend.js 991 B
build/checkout-blocks/shipping-methods-frontend.js 4.73 kB
build/checkout-blocks/terms-frontend.js 1.22 kB
build/checkout-blocks/totals-frontend.js 326 B
build/checkout-frontend.js 47.9 kB
build/checkout.js 45.5 kB
build/featured-category.js 13.2 kB
build/featured-product.js 13.5 kB
build/handpicked-products.js 7.4 kB
build/legacy-template.js 2.45 kB
build/mini-cart-component-frontend.js 16.6 kB
build/mini-cart-contents-block/empty-cart-frontend.js 364 B
build/mini-cart-contents-block/filled-cart-frontend.js 229 B
build/mini-cart-contents-block/footer--mini-cart-contents-block/products-table-frontend.js 4.69 kB
build/mini-cart-contents-block/footer-frontend.js 5.75 kB
build/mini-cart-contents-block/items-frontend.js 226 B
build/mini-cart-contents-block/products-table-frontend.js 290 B
build/mini-cart-contents-block/shopping-button-frontend.js 288 B
build/mini-cart-contents-block/title-frontend.js 367 B
build/mini-cart-contents.js 22.9 kB
build/mini-cart-frontend.js 1.72 kB
build/mini-cart.js 6.62 kB
build/price-filter-frontend.js 13 kB
build/price-filter.js 9 kB
build/price-format.js 1.19 kB
build/product-add-to-cart--product-button--product-category-list--product-image--product-price--product-r--a0326d00.js 222 B
build/product-add-to-cart--product-button--product-image--product-title.js 2.66 kB
build/product-add-to-cart--product-button.js 564 B
build/product-add-to-cart-frontend.js 6.95 kB
build/product-add-to-cart.js 6.63 kB
build/product-best-sellers.js 7.49 kB
build/product-button--product-category-list--product-image--product-price--product-rating--product-sale-b--e17c7c01.js 500 B
build/product-button-frontend.js 1.84 kB
build/product-button.js 1.09 kB
build/product-categories.js 2.78 kB
build/product-category-list-frontend.js 920 B
build/product-category-list.js 502 B
build/product-category.js 8.59 kB
build/product-image-frontend.js 1.83 kB
build/product-image.js 1.07 kB
build/product-new.js 7.77 kB
build/product-on-sale.js 8.09 kB
build/product-price-frontend.js 1.94 kB
build/product-price.js 1.5 kB
build/product-rating-frontend.js 1.15 kB
build/product-rating.js 731 B
build/product-sale-badge-frontend.js 1.09 kB
build/product-sale-badge.js 679 B
build/product-search.js 2.18 kB
build/product-sku-frontend.js 381 B
build/product-sku.js 381 B
build/product-stock-indicator-frontend.js 1.03 kB
build/product-stock-indicator.js 621 B
build/product-summary-frontend.js 1.33 kB
build/product-summary.js 916 B
build/product-tag-list-frontend.js 914 B
build/product-tag-list.js 497 B
build/product-tag.js 8.13 kB
build/product-title-frontend.js 1.29 kB
build/product-title.js 909 B
build/product-top-rated.js 8.01 kB
build/products-by-attribute.js 8.7 kB
build/reviews-by-category.js 11.3 kB
build/reviews-by-product.js 12.4 kB
build/reviews-frontend.js 7.02 kB
build/single-product-frontend.js 21.4 kB
build/single-product.js 10.1 kB
build/stock-filter-frontend.js 7.35 kB
build/stock-filter.js 7.26 kB
build/vendors--cart-blocks/cart-line-items--cart-blocks/cart-order-summary--cart-blocks/order-summary-shi--c02aad66-frontend.js 5.26 kB
build/vendors--cart-blocks/cart-line-items--checkout-blocks/order-summary-cart-items--mini-cart-contents---233ab542-frontend.js 3.14 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--5b8feb0b-frontend.js 4.74 kB
build/vendors--cart-blocks/order-summary-shipping--checkout-blocks/billing-address--checkout-blocks/order--decc3dc6-frontend.js 20.5 kB
build/vendors--mini-cart-contents-block/footer-frontend.js 6.86 kB
build/vendors--product-add-to-cart-frontend.js 7.53 kB
build/wc-blocks-data.js 9.87 kB
build/wc-blocks-editor-style-rtl.css 5.08 kB
build/wc-blocks-editor-style.css 5.08 kB
build/wc-blocks-google-analytics.js 1.56 kB
build/wc-blocks-middleware.js 930 B
build/wc-blocks-registry.js 2.7 kB
build/wc-blocks-shared-context.js 1.52 kB
build/wc-blocks-shared-hocs.js 1.14 kB
build/wc-blocks-style-rtl.css 22.1 kB
build/wc-blocks-style.css 22.1 kB
build/wc-blocks-vendors-style-rtl.css 1.28 kB
build/wc-blocks-vendors-style.css 1.28 kB
build/wc-blocks-vendors.js 59 kB
build/wc-blocks.js 2.63 kB
build/wc-payment-method-bacs.js 816 B
build/wc-payment-method-cheque.js 811 B
build/wc-payment-method-cod.js 909 B
build/wc-payment-method-paypal.js 837 B
build/wc-settings.js 2.61 kB

compressed-size-action

Copy link
Member

@nielslange nielslange left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! ⛴

Copy link
Contributor

@tarhi-saad tarhi-saad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @senadir, for fixing the local pickup tax calculation bug! You've done an excellent job! I've done multiple tests, including the above user-facing test, and all passed successfully! 🎉 So, it's looking good to me. I think we can ship it. But, please, @nielslange, if you can look into this as well, it would be fantastic! 🙌

EDIT:

Thank you, @nielslange, for looking into this PR!! I will merge it.

@tarhi-saad tarhi-saad merged commit f2ece16 into trunk Jun 27, 2022
@tarhi-saad tarhi-saad deleted the fix/local-pickup-taxes branch June 27, 2022 14:52
@nielslange nielslange changed the title Handles taxes for local pickup shipping Fix: Handle taxes for local pickup shipping Jul 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block: checkout Issues related to the checkout block. status: blocker Used on issues or pulls that block work from being released. type: bug The issue/PR concerns a confirmed bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Wrong 'Tax' value when using the 'Local pickup' shipping method
3 participants