WC_Cart_Totals::calculate_item_subtotals()
Subtotals are costs before discounts.
To prevent rounding issues we need to work with the inclusive price where possible otherwise we'll see errors such as when working with a 9.99 inc price, 20% VAT which would be 8.325 leading to totals being 1p off.
Pre tax coupons come off the price the customer thinks they are paying - tax is calculated afterwards.
e.g. $100 bike with $10 coupon = customer pays $90 and tax worked backwards from that.
Method of the class: WC_Cart_Totals{}
Hooks from the method
Return
null
. Nothing (null).
Usage
// protected - for code of main (parent) or child class $result = $this->calculate_item_subtotals();
Changelog
Since 3.2.0 | Introduced. |
WC_Cart_Totals::calculate_item_subtotals() WC Cart Totals::calculate item subtotals code WC 9.5.1
protected function calculate_item_subtotals() { $merged_subtotal_taxes = array(); // Taxes indexed by tax rate ID for storage later. $adjust_non_base_location_prices = apply_filters( 'woocommerce_adjust_non_base_location_prices', true ); $is_customer_vat_exempt = $this->cart->get_customer()->get_is_vat_exempt(); foreach ( $this->items as $item_key => $item ) { if ( $item->price_includes_tax ) { if ( $is_customer_vat_exempt ) { $item = $this->remove_item_base_taxes( $item ); } elseif ( $adjust_non_base_location_prices ) { $item = $this->adjust_non_base_location_price( $item ); } } $item->subtotal = $item->price; if ( $this->calculate_tax && $item->product->is_taxable() ) { $item->subtotal_taxes = WC_Tax::calc_tax( $item->subtotal, $item->tax_rates, $item->price_includes_tax ); $item->subtotal_tax = array_sum( array_map( array( $this, 'round_line_tax' ), $item->subtotal_taxes ) ); if ( $item->price_includes_tax ) { // Use unrounded taxes so we can re-calculate from the orders screen accurately later. $item->subtotal = $item->subtotal - array_sum( $item->subtotal_taxes ); } foreach ( $item->subtotal_taxes as $rate_id => $rate ) { if ( ! isset( $merged_subtotal_taxes[ $rate_id ] ) ) { $merged_subtotal_taxes[ $rate_id ] = 0; } $merged_subtotal_taxes[ $rate_id ] += $this->round_line_tax( $rate ); } } $this->cart->cart_contents[ $item_key ]['line_tax_data'] = array( 'subtotal' => wc_remove_number_precision_deep( $item->subtotal_taxes ) ); $this->cart->cart_contents[ $item_key ]['line_subtotal'] = wc_remove_number_precision( $item->subtotal ); $this->cart->cart_contents[ $item_key ]['line_subtotal_tax'] = wc_remove_number_precision( $item->subtotal_tax ); } $items_subtotal = $this->get_rounded_items_total( $this->get_values_for_total( 'subtotal' ) ); // Prices are not rounded here because they should already be rounded based on settings in `get_rounded_items_total` and in `round_line_tax` method calls. $this->set_total( 'items_subtotal', $items_subtotal ); $this->set_total( 'items_subtotal_tax', array_sum( $merged_subtotal_taxes ), 0 ); $this->cart->set_subtotal( $this->get_total( 'items_subtotal' ) ); $this->cart->set_subtotal_tax( $this->get_total( 'items_subtotal_tax' ) ); }