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.
This commit is contained in:
Nestor Soriano 2021-10-22 10:04:11 +02:00
parent 77ccfc56ca
commit 76c611b2d8
No known key found for this signature in database
GPG Key ID: 08110F3518C12CAD
2 changed files with 23 additions and 10 deletions

View File

@ -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 );

View File

@ -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
}
}