Merge pull request #22416 from woocommerce/fix/21871
Incorrect rounding of multiple tax rates per location
This commit is contained in:
commit
989865469e
|
@ -980,10 +980,16 @@ function wc_get_price_including_tax( $product, $args = array() ) {
|
|||
|
||||
if ( $product->is_taxable() ) {
|
||||
if ( ! wc_prices_include_tax() ) {
|
||||
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
|
||||
$taxes = WC_Tax::calc_tax( $line_price, $tax_rates, false );
|
||||
$tax_amount = WC_Tax::get_tax_total( $taxes );
|
||||
$return_price = round( $line_price + $tax_amount, wc_get_price_decimals() );
|
||||
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
|
||||
$taxes = WC_Tax::calc_tax( $line_price, $tax_rates, false );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$taxes_total = array_sum( $taxes );
|
||||
} else {
|
||||
$taxes_total = array_sum( array_map( 'wc_round_tax_total', $taxes ) );
|
||||
}
|
||||
|
||||
$return_price = round( $line_price + $taxes_total, wc_get_price_decimals() );
|
||||
} else {
|
||||
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
|
||||
$base_tax_rates = WC_Tax::get_base_tax_rates( $product->get_tax_class( 'unfiltered' ) );
|
||||
|
@ -994,8 +1000,14 @@ function wc_get_price_including_tax( $product, $args = array() ) {
|
|||
*/
|
||||
if ( ! empty( WC()->customer ) && WC()->customer->get_is_vat_exempt() ) { // @codingStandardsIgnoreLine.
|
||||
$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 );
|
||||
$remove_tax = array_sum( $remove_taxes );
|
||||
$return_price = round( $line_price - $remove_tax, wc_get_price_decimals() );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$remove_taxes_total = array_sum( $remove_taxes );
|
||||
} else {
|
||||
$remove_taxes_total = array_sum( array_map( 'wc_round_tax_total', $remove_taxes ) );
|
||||
}
|
||||
|
||||
$return_price = round( $line_price - $remove_taxes_total, wc_get_price_decimals() );
|
||||
|
||||
/**
|
||||
* The woocommerce_adjust_non_base_location_prices filter can stop base taxes being taken off when dealing with out of base locations.
|
||||
|
@ -1005,7 +1017,16 @@ function wc_get_price_including_tax( $product, $args = array() ) {
|
|||
} elseif ( $tax_rates !== $base_tax_rates && apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
|
||||
$base_taxes = WC_Tax::calc_tax( $line_price, $base_tax_rates, true );
|
||||
$modded_taxes = WC_Tax::calc_tax( $line_price - array_sum( $base_taxes ), $tax_rates, false );
|
||||
$return_price = round( $line_price - array_sum( $base_taxes ) + wc_round_tax_total( array_sum( $modded_taxes ), wc_get_price_decimals() ), wc_get_price_decimals() );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$base_taxes_total = array_sum( $base_taxes );
|
||||
$modded_taxes_total = array_sum( $modded_taxes );
|
||||
} else {
|
||||
$base_taxes_total = array_sum( array_map( 'wc_round_tax_total', $base_taxes ) );
|
||||
$modded_taxes_total = array_sum( array_map( 'wc_round_tax_total', $modded_taxes ) );
|
||||
}
|
||||
|
||||
$return_price = round( $line_price - $base_taxes_total + $modded_taxes_total, wc_get_price_decimals() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1044,7 +1065,7 @@ function wc_get_price_excluding_tax( $product, $args = array() ) {
|
|||
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
|
||||
$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 );
|
||||
$return_price = $line_price - array_sum( $remove_taxes );
|
||||
$return_price = $line_price - array_sum( $remove_taxes ); // Unrounded since we're dealing with tax inclusive prices. Matches logic in cart-totals class. @see adjust_non_base_location_price.
|
||||
} else {
|
||||
$return_price = $line_price;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,93 @@ class WC_Tests_Cart extends WC_Unit_Test_Case {
|
|||
WC()->customer->set_is_vat_exempt( false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for subtotals and multiple tax rounding.
|
||||
* Ticket:
|
||||
* https://github.com/woocommerce/woocommerce/issues/21871
|
||||
*/
|
||||
public function test_cart_subtotal_issue_21871() {
|
||||
update_option( 'woocommerce_prices_include_tax', 'no' );
|
||||
update_option( 'woocommerce_calc_taxes', 'yes' );
|
||||
update_option( 'woocommerce_tax_round_at_subtotal', 'no' );
|
||||
update_option( 'woocommerce_tax_display_cart', 'incl' );
|
||||
|
||||
// Create dummy product - price will be 10.
|
||||
$product = WC_Helper_Product::create_simple_product();
|
||||
$product->set_regular_price( 79 );
|
||||
$product->save();
|
||||
|
||||
// Add taxes.
|
||||
$tax_rate_025 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '0.2500',
|
||||
'tax_rate_name' => 'TAX025',
|
||||
'tax_rate_priority' => '1',
|
||||
'tax_rate_compound' => '0',
|
||||
'tax_rate_shipping' => '1',
|
||||
'tax_rate_order' => '1',
|
||||
'tax_rate_class' => '',
|
||||
)
|
||||
);
|
||||
|
||||
$tax_rate_06 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '6.0000',
|
||||
'tax_rate_name' => 'TAX06',
|
||||
'tax_rate_priority' => '2',
|
||||
'tax_rate_compound' => '0',
|
||||
'tax_rate_shipping' => '1',
|
||||
'tax_rate_order' => '1',
|
||||
'tax_rate_class' => '',
|
||||
)
|
||||
);
|
||||
|
||||
$tax_rate_015 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '1.5000',
|
||||
'tax_rate_name' => 'TAX015',
|
||||
'tax_rate_priority' => '3',
|
||||
'tax_rate_compound' => '0',
|
||||
'tax_rate_shipping' => '1',
|
||||
'tax_rate_order' => '1',
|
||||
'tax_rate_class' => '',
|
||||
)
|
||||
);
|
||||
|
||||
$tax_rate_01 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '1.000',
|
||||
'tax_rate_name' => 'TAX01',
|
||||
'tax_rate_priority' => '4',
|
||||
'tax_rate_compound' => '0',
|
||||
'tax_rate_shipping' => '1',
|
||||
'tax_rate_order' => '1',
|
||||
'tax_rate_class' => '',
|
||||
)
|
||||
);
|
||||
|
||||
// Add product to cart x1, calc and test
|
||||
WC()->cart->add_to_cart( $product->get_id(), 1 );
|
||||
WC()->cart->calculate_totals();
|
||||
$this->assertEquals( '85.92', number_format( WC()->cart->total, 2, '.', '' ) );
|
||||
$this->assertEquals( '85.92', number_format( WC()->cart->subtotal, 2, '.', '' ) );
|
||||
$this->assertEquals( '85.92', wc_get_price_including_tax( $product ) );
|
||||
|
||||
WC_Helper_Product::delete_product( $product->get_id() );
|
||||
WC_Tax::_delete_tax_rate( $tax_rate_025 );
|
||||
WC_Tax::_delete_tax_rate( $tax_rate_06 );
|
||||
WC_Tax::_delete_tax_rate( $tax_rate_015 );
|
||||
WC_Tax::_delete_tax_rate( $tax_rate_01 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test tax rounding.
|
||||
* Ticket:
|
||||
|
@ -98,7 +185,6 @@ class WC_Tests_Cart extends WC_Unit_Test_Case {
|
|||
|
||||
WC_Tax::_delete_tax_rate( $tax_rate_23 );
|
||||
WC_Tax::_delete_tax_rate( $tax_rate_5 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue