Remove extra calcs and populate item totals
This commit is contained in:
parent
95ffa441e0
commit
43cbcd04ef
|
@ -433,6 +433,9 @@ final class WC_Cart_Totals {
|
||||||
$item->total = $item->total;
|
$item->total = $item->total;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->object->cart_contents[ $item_key ]['line_total'] = wc_remove_number_precision( $item->total );
|
||||||
|
$this->object->cart_contents[ $item_key ]['line_tax'] = wc_remove_number_precision( $item->total_tax );
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->set_total( 'items_total', array_sum( array_values( wp_list_pluck( $this->items, 'total' ) ) ) );
|
$this->set_total( 'items_total', array_sum( array_values( wp_list_pluck( $this->items, 'total' ) ) ) );
|
||||||
|
@ -457,7 +460,7 @@ final class WC_Cart_Totals {
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
*/
|
*/
|
||||||
protected function calculate_item_subtotals() {
|
protected function calculate_item_subtotals() {
|
||||||
foreach ( $this->items as $item ) {
|
foreach ( $this->items as $item_key => $item ) {
|
||||||
if ( $item->price_includes_tax && apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
|
if ( $item->price_includes_tax && apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
|
||||||
$item = $this->adjust_non_base_location_price( $item );
|
$item = $this->adjust_non_base_location_price( $item );
|
||||||
}
|
}
|
||||||
|
@ -473,6 +476,9 @@ final class WC_Cart_Totals {
|
||||||
$item->subtotal = $item->subtotal - $item->subtotal_tax;
|
$item->subtotal = $item->subtotal - $item->subtotal_tax;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->object->cart_contents[ $item_key ]['line_subtotal'] = wc_remove_number_precision( $item->subtotal );
|
||||||
|
$this->object->cart_contents[ $item_key ]['line_subtotal_tax'] = wc_remove_number_precision( $item->subtotal_tax );
|
||||||
}
|
}
|
||||||
$this->set_total( 'items_subtotal', array_sum( array_values( wp_list_pluck( $this->items, 'subtotal' ) ) ) );
|
$this->set_total( 'items_subtotal', array_sum( array_values( wp_list_pluck( $this->items, 'subtotal' ) ) ) );
|
||||||
$this->set_total( 'items_subtotal_tax', array_sum( array_values( wp_list_pluck( $this->items, 'subtotal_tax' ) ) ) );
|
$this->set_total( 'items_subtotal_tax', array_sum( array_values( wp_list_pluck( $this->items, 'subtotal_tax' ) ) ) );
|
||||||
|
@ -583,18 +589,22 @@ final class WC_Cart_Totals {
|
||||||
$this->set_total( 'total', round( $this->get_total( 'items_total', true ) + $this->get_total( 'fees_total', true ) + $this->get_total( 'shipping_total', true ) + $this->get_total( 'tax_total', true ) + $this->get_total( 'shipping_tax_total', true ) ) );
|
$this->set_total( 'total', round( $this->get_total( 'items_total', true ) + $this->get_total( 'fees_total', true ) + $this->get_total( 'shipping_total', true ) + $this->get_total( 'tax_total', true ) + $this->get_total( 'shipping_tax_total', true ) ) );
|
||||||
|
|
||||||
// Add totals to cart object.
|
// Add totals to cart object.
|
||||||
$this->object->taxes = wp_list_pluck( $this->get_total( 'taxes' ), 'shipping_tax_total' );
|
$this->object->taxes = wp_list_pluck( $this->get_total( 'taxes' ), 'shipping_tax_total' );
|
||||||
$this->object->shipping_taxes = wp_list_pluck( $this->get_total( 'taxes' ), 'tax_total' );
|
$this->object->shipping_taxes = wp_list_pluck( $this->get_total( 'taxes' ), 'tax_total' );
|
||||||
$this->object->tax_total = $this->get_total( 'tax_total' );
|
$this->object->cart_contents_total = $this->get_total( 'items_total' );
|
||||||
$this->object->total = $this->get_total( 'total' );
|
$this->object->tax_total = $this->get_total( 'tax_total' );
|
||||||
|
$this->object->total = $this->get_total( 'total' );
|
||||||
|
$this->object->discount_cart = $this->get_total( 'discounts_total' );
|
||||||
|
$this->object->discount_cart_tax = $this->get_total( 'discounts_tax_total' );
|
||||||
|
|
||||||
// Allow plugins to hook and alter totals before final total is calculated.
|
// Allow plugins to hook and alter totals before final total is calculated.
|
||||||
if ( has_action( 'woocommerce_calculate_totals' ) ) {
|
if ( has_action( 'woocommerce_calculate_totals' ) ) {
|
||||||
do_action( 'woocommerce_calculate_totals', $this->object );
|
do_action( 'woocommerce_calculate_totals', $this->object );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @TODO: Fix logic bug. Currently totals are always 0.
|
||||||
// Allow plugins to filter the grand total, and sum the cart totals in case of modifications.
|
// Allow plugins to filter the grand total, and sum the cart totals in case of modifications.
|
||||||
$totals_to_sum = wc_add_number_precision_deep( array( $this->object->cart_contents_total, $this->object->tax_total, $this->object->shipping_tax_total, $this->object->shipping_total, $this->object->fee_total ) );
|
// $totals_to_sum = wc_add_number_precision_deep( array( $this->object->cart_contents_total, $this->object->tax_total, $this->object->shipping_tax_total, $this->object->shipping_total, $this->object->fee_total ) );
|
||||||
$this->object->total = max( 0, apply_filters( 'woocommerce_calculated_total', wc_remove_number_precision( round( array_sum( $totals_to_sum ) ) ), $this->object ) );
|
// $this->object->total = max( 0, apply_filters( 'woocommerce_calculated_total', wc_remove_number_precision( round( array_sum( $totals_to_sum ) ) ), $this->object ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,197 +1121,12 @@ class WC_Cart extends WC_Legacy_Cart {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tax_rates = array();
|
$cart = $this->get_cart();
|
||||||
$shop_tax_rates = array();
|
|
||||||
$cart = $this->get_cart();
|
|
||||||
|
|
||||||
// Order cart items by price so coupon logic is 'fair' for customers and not based on order added to cart.
|
// Order cart items by price so coupon logic is 'fair' for customers and not based on order added to cart.
|
||||||
uasort( $cart, apply_filters( 'woocommerce_sort_by_subtotal_callback', array( $this, 'sort_by_subtotal' ) ) );
|
uasort( $cart, apply_filters( 'woocommerce_sort_by_subtotal_callback', array( $this, 'sort_by_subtotal' ) ) );
|
||||||
|
|
||||||
/**
|
new WC_Cart_Totals( $this );
|
||||||
* Calculate totals for items.
|
|
||||||
*/
|
|
||||||
foreach ( $cart as $cart_item_key => $values ) {
|
|
||||||
|
|
||||||
$product = $values['data'];
|
|
||||||
|
|
||||||
// Prices
|
|
||||||
$base_price = $product->get_price();
|
|
||||||
$line_price = $product->get_price() * $values['quantity'];
|
|
||||||
|
|
||||||
// Tax data
|
|
||||||
$taxes = array();
|
|
||||||
$discounted_taxes = array();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* No tax to calculate.
|
|
||||||
*/
|
|
||||||
if ( ! $product->is_taxable() ) {
|
|
||||||
|
|
||||||
// Discounted Price (price with any pre-tax discounts applied)
|
|
||||||
$discounted_price = $this->get_discounted_price( $values, $base_price, true );
|
|
||||||
$line_subtotal_tax = 0;
|
|
||||||
$line_subtotal = $line_price;
|
|
||||||
$line_tax = 0;
|
|
||||||
$line_total = round( $discounted_price * $values['quantity'], wc_get_rounding_precision() );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prices include tax.
|
|
||||||
*/
|
|
||||||
} elseif ( $this->prices_include_tax ) {
|
|
||||||
|
|
||||||
if ( empty( $shop_tax_rates[ $product->get_tax_class( 'unfiltered' ) ] ) ) {
|
|
||||||
$shop_tax_rates[ $product->get_tax_class( 'unfiltered' ) ] = WC_Tax::get_base_tax_rates( $product->get_tax_class( 'unfiltered' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $tax_rates[ $product->get_tax_class() ] ) ) {
|
|
||||||
$tax_rates[ $product->get_tax_class() ] = WC_Tax::get_rates( $product->get_tax_class() );
|
|
||||||
}
|
|
||||||
|
|
||||||
$base_tax_rates = $shop_tax_rates[ $product->get_tax_class( 'unfiltered' ) ];
|
|
||||||
$item_tax_rates = $tax_rates[ $product->get_tax_class() ];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ADJUST TAX - Calculations when base tax is not equal to the item tax.
|
|
||||||
*
|
|
||||||
* The woocommerce_adjust_non_base_location_prices filter can stop base taxes being taken off when dealing with out of base locations.
|
|
||||||
* e.g. If a product costs 10 including tax, all users will pay 10 regardless of location and taxes.
|
|
||||||
* This feature is experimental @since 2.4.7 and may change in the future. Use at your risk.
|
|
||||||
*/
|
|
||||||
if ( $item_tax_rates !== $base_tax_rates && apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
|
|
||||||
|
|
||||||
// Work out a new base price without the shop's base tax
|
|
||||||
$taxes = WC_Tax::calc_tax( $line_price, $base_tax_rates, true, true );
|
|
||||||
|
|
||||||
// Now we have a new item price (excluding TAX)
|
|
||||||
$line_subtotal = round( $line_price - array_sum( $taxes ), wc_get_rounding_precision() );
|
|
||||||
$taxes = WC_Tax::calc_tax( $line_subtotal, $item_tax_rates );
|
|
||||||
$line_subtotal_tax = array_sum( $taxes );
|
|
||||||
|
|
||||||
// Adjusted price (this is the price including the new tax rate)
|
|
||||||
$adjusted_price = ( $line_subtotal + $line_subtotal_tax ) / $values['quantity'];
|
|
||||||
|
|
||||||
// Apply discounts and get the discounted price FOR A SINGLE ITEM
|
|
||||||
$discounted_price = $this->get_discounted_price( $values, $adjusted_price, true );
|
|
||||||
|
|
||||||
// Convert back to line price
|
|
||||||
$discounted_line_price = $discounted_price * $values['quantity'];
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular tax calculation (customer inside base and the tax class is unmodified.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Work out a new base price without the item tax
|
|
||||||
$taxes = WC_Tax::calc_tax( $line_price, $item_tax_rates, true );
|
|
||||||
|
|
||||||
// Now we have a new item price (excluding TAX)
|
|
||||||
$line_subtotal = $line_price - array_sum( $taxes );
|
|
||||||
$line_subtotal_tax = array_sum( $taxes );
|
|
||||||
|
|
||||||
// Calc prices and tax (discounted)
|
|
||||||
$discounted_price = $this->get_discounted_price( $values, $base_price, true );
|
|
||||||
|
|
||||||
// Convert back to line price
|
|
||||||
$discounted_line_price = $discounted_price * $values['quantity'];
|
|
||||||
|
|
||||||
// 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
|
|
||||||
foreach ( array_keys( $this->taxes + $discounted_taxes ) as $key ) {
|
|
||||||
$this->taxes[ $key ] = ( isset( $discounted_taxes[ $key ] ) ? $discounted_taxes[ $key ] : 0 ) + ( isset( $this->taxes[ $key ] ) ? $this->taxes[ $key ] : 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prices exclude tax.
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
if ( empty( $tax_rates[ $product->get_tax_class() ] ) ) {
|
|
||||||
$tax_rates[ $product->get_tax_class() ] = WC_Tax::get_rates( $product->get_tax_class() );
|
|
||||||
}
|
|
||||||
|
|
||||||
$item_tax_rates = $tax_rates[ $product->get_tax_class() ];
|
|
||||||
|
|
||||||
// Work out a new base price without the shop's base tax
|
|
||||||
$taxes = WC_Tax::calc_tax( $line_price, $item_tax_rates );
|
|
||||||
|
|
||||||
// Now we have the item price (excluding TAX)
|
|
||||||
$line_subtotal = $line_price;
|
|
||||||
$line_subtotal_tax = array_sum( $taxes );
|
|
||||||
|
|
||||||
// Now calc product rates
|
|
||||||
$discounted_price = $this->get_discounted_price( $values, $base_price, true );
|
|
||||||
$discounted_taxes = WC_Tax::calc_tax( $discounted_price * $values['quantity'], $item_tax_rates );
|
|
||||||
$discounted_tax_amount = array_sum( $discounted_taxes );
|
|
||||||
$line_tax = $discounted_tax_amount;
|
|
||||||
$line_total = $discounted_price * $values['quantity'];
|
|
||||||
|
|
||||||
// Tax rows - merge the totals we just got
|
|
||||||
foreach ( array_keys( $this->taxes + $discounted_taxes ) as $key ) {
|
|
||||||
$this->taxes[ $key ] = ( isset( $discounted_taxes[ $key ] ) ? $discounted_taxes[ $key ] : 0 ) + ( isset( $this->taxes[ $key ] ) ? $this->taxes[ $key ] : 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cart contents total is based on discounted prices and is used for the final total calculation
|
|
||||||
$this->cart_contents_total += $line_total;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store costs + taxes for lines. For tax inclusive prices, we do some extra rounding logic so the stored
|
|
||||||
* values "add up" when viewing the order in admin. This does have the disadvantage of not being able to
|
|
||||||
* recalculate the tax total/subtotal accurately in the future, but it does ensure the data looks correct.
|
|
||||||
*
|
|
||||||
* Tax exclusive prices are not affected.
|
|
||||||
*/
|
|
||||||
if ( ! $product->is_taxable() || $this->prices_include_tax ) {
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_total'] = round( $line_total + $line_tax - wc_round_tax_total( $line_tax ), $this->dp );
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_subtotal'] = round( $line_subtotal + $line_subtotal_tax - wc_round_tax_total( $line_subtotal_tax ), $this->dp );
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_tax'] = wc_round_tax_total( $line_tax );
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_subtotal_tax'] = wc_round_tax_total( $line_subtotal_tax );
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_tax_data'] = array( 'total' => array_map( 'wc_round_tax_total', $discounted_taxes ), 'subtotal' => array_map( 'wc_round_tax_total', $taxes ) );
|
|
||||||
} else {
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_total'] = $line_total;
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_subtotal'] = $line_subtotal;
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_tax'] = $line_tax;
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_subtotal_tax'] = $line_subtotal_tax;
|
|
||||||
$this->cart_contents[ $cart_item_key ]['line_tax_data'] = array( 'total' => $discounted_taxes, 'subtotal' => $taxes );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only calculate the grand total + shipping if on the cart/checkout
|
|
||||||
if ( is_checkout() || is_cart() || defined( 'WOOCOMMERCE_CHECKOUT' ) || defined( 'WOOCOMMERCE_CART' ) ) {
|
|
||||||
|
|
||||||
// Calculate the Shipping.
|
|
||||||
$local_pickup_methods = apply_filters( 'woocommerce_local_pickup_methods', array( 'legacy_local_pickup', 'local_pickup' ) );
|
|
||||||
$had_local_pickup = 0 < count( array_intersect( wc_get_chosen_shipping_method_ids(), $local_pickup_methods ) );
|
|
||||||
$this->calculate_shipping();
|
|
||||||
$has_local_pickup = 0 < count( array_intersect( wc_get_chosen_shipping_method_ids(), $local_pickup_methods ) );
|
|
||||||
|
|
||||||
// If methods changed and local pickup is selected, we need to do a recalculation of taxes.
|
|
||||||
if ( true === apply_filters( 'woocommerce_apply_base_tax_for_local_pickup', true ) && $had_local_pickup !== $has_local_pickup ) {
|
|
||||||
return $this->calculate_totals();
|
|
||||||
}
|
|
||||||
|
|
||||||
new WC_Cart_Totals( $this );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Set tax total to sum of all tax rows
|
|
||||||
$this->tax_total = WC_Tax::get_tax_total( $this->taxes );
|
|
||||||
|
|
||||||
// VAT exemption done at this point - so all totals are correct before exemption
|
|
||||||
if ( $this->get_customer()->get_is_vat_exempt() ) {
|
|
||||||
$this->remove_taxes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_action( 'woocommerce_after_calculate_totals', $this );
|
do_action( 'woocommerce_after_calculate_totals', $this );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue