Merge pull request #22416 from woocommerce/fix/21871

Incorrect rounding of multiple tax rates per location
This commit is contained in:
Claudiu Lodromanean 2019-01-16 09:32:51 -08:00 committed by GitHub
commit 989865469e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 116 additions and 9 deletions

View File

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

View File

@ -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 );
}
/**