From 76c611b2d897b21ab9d498a2a6b49ee55425d9fd Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 22 Oct 2021 10:04:11 +0200 Subject: [PATCH] Fix: wc_get_price_excluding_tax when an order with no customer is passed PR #30692 modified 'wc_get_price_excluding_tax' so that if an order is passed its customer will be passed to WC_Tax::get_rates in order to use the proper location for the taxes to be discounted. The problem is that when the order has no customer (it's "Guest") an invalid customer (id=0) is passed, which has no location, and thus no taxes are deducted whatsoever. The fix consists of checking if the customer id from the order is 0, and in that case no customer is passed to WC_Tax::get_rates, thus the shop location is used for the taxes. --- .../includes/wc-product-functions.php | 3 +- .../includes/wc-product-functions-test.php | 30 +++++++++++++------ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/woocommerce/includes/wc-product-functions.php b/plugins/woocommerce/includes/wc-product-functions.php index 902dceede73..fb71806cb07 100644 --- a/plugins/woocommerce/includes/wc-product-functions.php +++ b/plugins/woocommerce/includes/wc-product-functions.php @@ -1084,7 +1084,8 @@ function wc_get_price_excluding_tax( $product, $args = array() ) { if ( $product->is_taxable() && wc_prices_include_tax() ) { $order = ArrayUtil::get_value_or_default( $args, 'order' ); - $customer = $order ? wc_get_container()->get( LegacyProxy::class )->get_instance_of( WC_Customer::class, $order->get_customer_id() ) : null; + $customer_id = $order ? $order->get_customer_id() : 0; + $customer = $customer_id ? wc_get_container()->get( LegacyProxy::class )->get_instance_of( WC_Customer::class, $customer_id ) : null; $tax_rates = WC_Tax::get_rates( $product->get_tax_class(), $customer ); $base_tax_rates = WC_Tax::get_base_tax_rates( $product->get_tax_class( 'unfiltered' ) ); $remove_taxes = apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ? WC_Tax::calc_tax( $line_price, $base_tax_rates, true ) : WC_Tax::calc_tax( $line_price, $tax_rates, true ); diff --git a/plugins/woocommerce/tests/php/includes/wc-product-functions-test.php b/plugins/woocommerce/tests/php/includes/wc-product-functions-test.php index 26fedee2c6a..8c7c55e05b4 100644 --- a/plugins/woocommerce/tests/php/includes/wc-product-functions-test.php +++ b/plugins/woocommerce/tests/php/includes/wc-product-functions-test.php @@ -16,12 +16,14 @@ class WC_Product_Functions_Tests extends \WC_Unit_Test_Case { /** * @testdox If 'wc_get_price_excluding_tax' gets an order as argument, it passes the order customer to 'WC_Tax::get_rates'. * - * @testWith [true] - * [false] + * @testWith [true, 1] + * [true, 0] + * [false, null] * - * @param bool $pass_order Whether an order is passed to 'wc_get_price_excluding_tax' or not. + * @param bool $pass_order Whether an order is passed to 'wc_get_price_excluding_tax' or not. + * @param int|null $customer_id Id of the customer associated to the order. */ - public function test_wc_get_price_excluding_tax_passes_order_customer_to_get_rates_if_order_is_available( $pass_order ) { + public function test_wc_get_price_excluding_tax_passes_order_customer_to_get_rates_if_order_is_available( $pass_order, $customer_id ) { $customer_passed_to_get_rates = false; $customer_id_passed_to_wc_customer_constructor = false; @@ -48,7 +50,7 @@ class WC_Product_Functions_Tests extends \WC_Unit_Test_Case { ) ); - // phpcs:disable Squiz.Commenting.FunctionComment.Missing + // phpcs:disable Squiz.Commenting $product = new class() extends WC_Product { public function get_price( $context = 'view' ) { @@ -75,16 +77,26 @@ class WC_Product_Functions_Tests extends \WC_Unit_Test_Case { ); if ( $pass_order ) { - $order = new class() { + $order = new class( $customer_id ) { + private $customer_id; + + public function __construct( $customer_id ) { + $this->customer_id = $customer_id; + } + public function get_customer_id() { - return 1; + return $this->customer_id; } }; wc_get_price_excluding_tax( $product, array( 'order' => $order ) ); $this->assertEquals( $order->get_customer_id(), $customer_id_passed_to_wc_customer_constructor ); - $this->assertSame( $customer, $customer_passed_to_get_rates ); + if ( $customer_id ) { + $this->assertSame( $customer, $customer_passed_to_get_rates ); + } else { + $this->assertNull( $customer_passed_to_get_rates ); + } } else { wc_get_price_excluding_tax( $product ); @@ -92,6 +104,6 @@ class WC_Product_Functions_Tests extends \WC_Unit_Test_Case { $this->assertNull( $customer_passed_to_get_rates ); } - // phpcs:enable Squiz.Commenting.FunctionComment.Missing + // phpcs:enable Squiz.Commenting } }