Discount rounding logic improvements
Instead of rounding the single item discount amount, this rounds the line to the store DP setting before running tax logic. Fixes #10963 Also works with #10573 Includes unit tests
This commit is contained in:
parent
26db1bb52b
commit
e00c3450c5
|
@ -1255,7 +1255,7 @@ class WC_Cart {
|
|||
$line_subtotal_tax = 0;
|
||||
$line_subtotal = $line_price;
|
||||
$line_tax = 0;
|
||||
$line_total = WC_Tax::round( $discounted_price * $values['quantity'] );
|
||||
$line_total = round( $discounted_price * $values['quantity'], WC_ROUNDING_PRECISION );
|
||||
|
||||
/**
|
||||
* Prices include tax.
|
||||
|
@ -1285,11 +1285,16 @@ class WC_Cart {
|
|||
// Adjusted price (this is the price including the new tax rate)
|
||||
$adjusted_price = ( $line_subtotal + $line_subtotal_tax ) / $values['quantity'];
|
||||
|
||||
// Apply discounts
|
||||
// Apply discounts and get the discounted price FOR A SINGLE ITEM
|
||||
$discounted_price = $this->get_discounted_price( $values, $adjusted_price, true );
|
||||
$discounted_taxes = WC_Tax::calc_tax( $discounted_price * $values['quantity'], $item_tax_rates, true );
|
||||
|
||||
// Convert back to line price and round nicely
|
||||
$discounted_line_price = round( $discounted_price * $values['quantity'], $this->dp );
|
||||
|
||||
// Now use rounded line price to get taxes.
|
||||
$discounted_taxes = WC_Tax::calc_tax( $discounted_line_price, $item_tax_rates, true );
|
||||
$line_tax = array_sum( $discounted_taxes );
|
||||
$line_total = ( $discounted_price * $values['quantity'] ) - $line_tax;
|
||||
$line_total = $discounted_line_price - $line_tax;
|
||||
|
||||
/**
|
||||
* Regular tax calculation (customer inside base and the tax class is unmodified.
|
||||
|
@ -1305,9 +1310,14 @@ class WC_Cart {
|
|||
|
||||
// Calc prices and tax (discounted)
|
||||
$discounted_price = $this->get_discounted_price( $values, $base_price, true );
|
||||
$discounted_taxes = WC_Tax::calc_tax( $discounted_price * $values['quantity'], $item_tax_rates, true );
|
||||
$line_tax = array_sum( $discounted_taxes );
|
||||
$line_total = ( $discounted_price * $values['quantity'] ) - $line_tax;
|
||||
|
||||
// Convert back to line price and round nicely
|
||||
$discounted_line_price = round( $discounted_price * $values['quantity'], $this->dp );
|
||||
|
||||
// Now use rounded line price to get taxes.
|
||||
$discounted_taxes = WC_Tax::calc_tax( $discounted_line_price, $item_tax_rates, true );
|
||||
$line_tax = array_sum( $discounted_taxes );
|
||||
$line_total = $discounted_line_price - $line_tax;
|
||||
}
|
||||
|
||||
// Tax rows - merge the totals we just got
|
||||
|
|
|
@ -748,7 +748,7 @@ class WC_Coupon {
|
|||
}
|
||||
}
|
||||
|
||||
$discount = wc_cart_round_discount( $discount, wc_get_price_decimals() );
|
||||
$discount = wc_cart_round_discount( $discount, WC_ROUNDING_PRECISION );
|
||||
|
||||
return apply_filters( 'woocommerce_coupon_get_discount_amount', $discount, $discounting_amount, $cart_item, $single, $this );
|
||||
}
|
||||
|
|
|
@ -15,11 +15,15 @@ class WC_Tests_Cart extends WC_Unit_Test_Case {
|
|||
* Due to discounts being split amongst products in cart.
|
||||
*/
|
||||
public function test_cart_get_discounted_price() {
|
||||
global $wpdb;
|
||||
|
||||
// We need this to have the calculate_totals() method calculate totals
|
||||
if ( ! defined( 'WOOCOMMERCE_CHECKOUT' ) ) {
|
||||
define( 'WOOCOMMERCE_CHECKOUT', true );
|
||||
}
|
||||
|
||||
# Test case 1 #10963
|
||||
|
||||
// Create dummy coupon - fixed cart, 1 value
|
||||
$coupon = WC_Helper_Coupon::create_coupon();
|
||||
|
||||
|
@ -51,6 +55,42 @@ class WC_Tests_Cart extends WC_Unit_Test_Case {
|
|||
WC()->cart->empty_cart();
|
||||
WC()->cart->remove_coupons();
|
||||
|
||||
# Test case 2 #10573
|
||||
update_post_meta( $product->id, '_regular_price', '29.95' );
|
||||
update_post_meta( $product->id, '_price', '29.95' );
|
||||
update_post_meta( $coupon->id, 'discount_type', 'percent' );
|
||||
update_post_meta( $coupon->id, 'coupon_amount', '10' );
|
||||
update_option( 'woocommerce_prices_include_tax', 'yes' );
|
||||
update_option( 'woocommerce_calc_taxes', 'yes' );
|
||||
$tax_rate = array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '10.0000',
|
||||
'tax_rate_name' => 'TAX',
|
||||
'tax_rate_priority' => '1',
|
||||
'tax_rate_compound' => '0',
|
||||
'tax_rate_shipping' => '1',
|
||||
'tax_rate_order' => '1',
|
||||
'tax_rate_class' => ''
|
||||
);
|
||||
WC_Tax::_insert_tax_rate( $tax_rate );
|
||||
$product = wc_get_product( $product->id );
|
||||
|
||||
WC()->cart->add_to_cart( $product->id, 1 );
|
||||
WC()->cart->add_discount( $coupon->code );
|
||||
|
||||
WC()->cart->calculate_totals();
|
||||
$cart_item = current( WC()->cart->get_cart() );
|
||||
$this->assertEquals( '24.51', number_format( $cart_item['line_total'], 2, '.', '' ) );
|
||||
|
||||
// Cleanup
|
||||
$wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_tax_rates" );
|
||||
$wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_tax_rate_locations" );
|
||||
WC()->cart->empty_cart();
|
||||
WC()->cart->remove_coupons();
|
||||
update_option( 'woocommerce_prices_include_tax', 'no' );
|
||||
update_option( 'woocommerce_calc_taxes', 'no' );
|
||||
|
||||
// Delete coupon
|
||||
WC_Helper_Coupon::delete_coupon( $coupon->id );
|
||||
|
||||
|
|
Loading…
Reference in New Issue