Merge pull request #16289 from woocommerce/feature/15500

Use WC_Cart_Totals to calculate WC_Cart totals
This commit is contained in:
Claudiu Lodromanean 2017-07-28 14:41:17 -07:00 committed by GitHub
commit 5fb33e3aaa
2 changed files with 13 additions and 126 deletions

View File

@ -497,7 +497,7 @@ final class WC_Cart_Totals {
}
$this->discount_totals = $discounts->get_discounts_by_item( true );
$this->totals['discounts_total'] = array_sum( $this->discount_totals );
$this->totals['discounts_total'] = ! empty( $this->discount_totals ) ? array_sum( $this->discount_totals ) : 0;
$this->object->coupon_discount_amounts = $discounts->get_discounts_by_coupon();
// See how much tax was 'discounted' per item and per coupon.

View File

@ -1126,107 +1126,6 @@ class WC_Cart {
$shop_tax_rates = array();
$cart = $this->get_cart();
/**
* Calculate subtotals for items. This is done first so that discount logic can use the values.
*/
foreach ( $cart as $cart_item_key => $values ) {
$product = $values['data'];
$line_price = $product->get_price() * $values['quantity'];
$line_subtotal = 0;
$line_subtotal_tax = 0;
/**
* No tax to calculate.
*/
if ( ! $product->is_taxable() ) {
// Subtotal is the undiscounted price
$this->subtotal += $line_price;
$this->subtotal_ex_tax += $line_price;
/**
* Prices include tax.
*
* 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.
*/
} elseif ( $this->prices_include_tax ) {
// Get base tax rates
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' ) );
}
// Get item tax rates
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 = $line_price - array_sum( $taxes );
// Now add modified taxes
$tax_result = WC_Tax::calc_tax( $line_subtotal, $item_tax_rates );
$line_subtotal_tax = array_sum( $tax_result );
/**
* Regular tax calculation (customer inside base and the tax class is unmodified.
*/
} else {
// Calc tax normally
$taxes = WC_Tax::calc_tax( $line_price, $item_tax_rates, true );
$line_subtotal_tax = array_sum( $taxes );
$line_subtotal = $line_price - array_sum( $taxes );
}
/**
* Prices exclude tax.
*
* This calculation is simpler - work with the base, untaxed price.
*/
} else {
// Get item tax rates
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() ];
// Base tax for line before discount - we will store this in the order data
$taxes = WC_Tax::calc_tax( $line_price, $item_tax_rates );
$line_subtotal_tax = array_sum( $taxes );
$line_subtotal = $line_price;
}
// Add to main subtotal
$this->subtotal += $line_subtotal + $line_subtotal_tax;
$this->subtotal_ex_tax += $line_subtotal;
}
// 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' ) ) );
@ -1262,6 +1161,14 @@ class WC_Cart {
*/
} 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() ];
@ -1329,6 +1236,9 @@ class WC_Cart {
* 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() ];
@ -1391,30 +1301,7 @@ class WC_Cart {
return $this->calculate_totals();
}
// Trigger the fees API where developers can add fees to the cart
$this->calculate_fees();
// Total up/round taxes and shipping taxes
if ( $this->round_at_subtotal ) {
$this->tax_total = WC_Tax::get_tax_total( $this->taxes );
$this->shipping_tax_total = WC_Tax::get_tax_total( $this->shipping_taxes );
$this->taxes = array_map( array( 'WC_Tax', 'round' ), $this->taxes );
$this->shipping_taxes = array_map( array( 'WC_Tax', 'round' ), $this->shipping_taxes );
} else {
$this->tax_total = array_sum( $this->taxes );
$this->shipping_tax_total = array_sum( $this->shipping_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();
}
// Allow plugins to hook and alter totals before final total is calculated
do_action( 'woocommerce_calculate_totals', $this );
// Grand Total - Discounted product prices, discounted tax, shipping cost + tax
$this->total = max( 0, apply_filters( 'woocommerce_calculated_total', round( $this->cart_contents_total + $this->tax_total + $this->shipping_tax_total + $this->shipping_total + $this->fee_total, $this->dp ), $this ) );
new WC_Cart_Totals( $this );
} else {