Round discount totals

This commit is contained in:
Mike Jolley 2015-04-10 10:28:46 +01:00
parent ad6c173757
commit 68194bf0ed
2 changed files with 52 additions and 52 deletions

View File

@ -1298,6 +1298,9 @@ class WC_Cart {
$this->cart_contents[ $cart_item_key ]['line_tax_data'] = array( 'total' => $discounted_taxes, 'subtotal' => $taxes );
}
// Round cart contents
$this->cart_contents_total = round( $this->cart_contents_total, $this->dp );
// Only calculate the grand total + shipping if on the cart/checkout
if ( is_checkout() || is_cart() || defined('WOOCOMMERCE_CHECKOUT') || defined('WOOCOMMERCE_CART') ) {
@ -1326,6 +1329,14 @@ class WC_Cart {
// Allow plugins to hook and alter totals before final total is calculated
do_action( 'woocommerce_calculate_totals', $this );
/*echo '<pre>';
echo 'Cart Contents Total: ' . $this->cart_contents_total . '<br/>';
echo 'Tax Total: ' . $this->tax_total . '<br/>';
echo 'Shipping Tax Total: ' . $this->shipping_tax_total . '<br/>';
echo 'Shipping Total: ' . $this->shipping_total . '<br/>';
echo 'Fee Total: ' . $this->fee_total . '<br/>';
echo '</pre>';*/
// 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 ) );
@ -1740,11 +1751,11 @@ class WC_Cart {
public function get_coupon_discount_amount( $code, $ex_tax = true ) {
$discount_amount = isset( $this->coupon_discount_amounts[ $code ] ) ? $this->coupon_discount_amounts[ $code ] : 0;
if ( $ex_tax ) {
return $discount_amount;
} else {
return $discount_amount + $this->get_coupon_discount_tax_amount( $code );
if ( ! $ex_tax ) {
$discount_amount += $this->get_coupon_discount_tax_amount( $code );
}
return round( $discount_amount, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
}
/**
@ -1754,7 +1765,7 @@ class WC_Cart {
* @return float discount amount
*/
public function get_coupon_discount_tax_amount( $code ) {
return isset( $this->coupon_discount_tax_amounts[ $code ] ) ? $this->coupon_discount_tax_amounts[ $code ] : 0;
return round( isset( $this->coupon_discount_tax_amounts[ $code ] ) ? $this->coupon_discount_tax_amounts[ $code ] : 0, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
}
/**
@ -1809,7 +1820,7 @@ class WC_Cart {
foreach ( $this->coupons as $code => $coupon ) {
if ( $coupon->is_valid() && ( $coupon->is_valid_for_product( $product, $values ) || $coupon->is_valid_for_cart() ) ) {
$discount_amount = $coupon->get_discount_amount( ( 'yes' === get_option( 'woocommerce_calc_discounts_sequentially', 'no' ) ? $price : $undiscounted_price ), $values, $single = true );
$discount_amount = $coupon->get_discount_amount( ( 'yes' === get_option( 'woocommerce_calc_discounts_sequentially', 'no' ) ? $price : $undiscounted_price ), $values, true );
$discount_amount = min( $price, $discount_amount );
$price = max( $price - $discount_amount, 0 );
@ -2149,7 +2160,7 @@ class WC_Cart {
* @return float
*/
public function get_cart_discount_total() {
return $this->discount_cart;
return round( $this->discount_cart, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
}
/**
@ -2158,7 +2169,7 @@ class WC_Cart {
* @return float
*/
public function get_cart_discount_tax_total() {
return $this->discount_cart_tax;
return round( $this->discount_cart_tax, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
}
/**
@ -2167,8 +2178,8 @@ class WC_Cart {
* @return mixed formatted price or false if there are none
*/
public function get_total_discount() {
if ( $this->discount_cart ) {
$total_discount = wc_price( $this->discount_cart );
if ( $this->get_cart_discount_total() ) {
$total_discount = wc_price( $this->get_cart_discount_total() );
} else {
$total_discount = false;
}
@ -2183,8 +2194,8 @@ class WC_Cart {
*/
public function get_discounts_before_tax() {
_deprecated_function( 'get_discounts_before_tax', '2.3', 'get_total_discount' );
if ( $this->discount_cart ) {
$discounts_before_tax = wc_price( $this->discount_cart );
if ( $this->get_cart_discount_total() ) {
$discounts_before_tax = wc_price( $this->get_cart_discount_total() );
} else {
$discounts_before_tax = false;
}

View File

@ -600,60 +600,49 @@ class WC_Coupon {
* @return float Amount this coupon has discounted
*/
public function get_discount_amount( $discounting_amount, $cart_item = null, $single = false ) {
$discount = 0;
$discount = 0;
$cart_item_qty = is_null( $cart_item ) ? 1 : $cart_item['quantity'];
if ( $this->is_type( 'fixed_product' ) ) {
if ( $this->is_type( array( 'percent_product', 'percent' ) ) ) {
$discount = $this->coupon_amount * ( $discounting_amount / 100 );
$discount = $discounting_amount < $this->coupon_amount ? $discounting_amount : $this->coupon_amount;
} elseif ( $this->is_type( 'fixed_cart' ) && ! is_null( $cart_item ) && WC()->cart->subtotal_ex_tax ) {
/**
* This is the most complex discount - we need to divide the discount between rows based on their price in
* proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows
* with no price (free) don't get discounted.
*
* Get item discount by dividing item cost by subtotal to get a %
*
* Uses price inc tax if prices include tax to work around https://github.com/woothemes/woocommerce/issues/7669
*/
$discount_percent = ( $cart_item['data']->get_price() * $cart_item_qty ) / ( wc_prices_include_tax() ? WC()->cart->subtotal : WC()->cart->subtotal_ex_tax );
$discount = ( $this->coupon_amount * $discount_percent ) / $cart_item_qty;
// If dealing with a line and not a single item, we need to multiple fixed discount by cart item qty.
if ( ! $single && ! is_null( $cart_item ) ) {
// Discount for the line.
$discount = $discount * $cart_item['quantity'];
}
} elseif ( $this->is_type( array( 'percent_product', 'percent' ) ) ) {
$discount = round( ( $discounting_amount / 100 ) * $this->coupon_amount, WC()->cart->dp );
} elseif ( $this->is_type( 'fixed_cart' ) ) {
if ( ! is_null( $cart_item ) ) {
/**
* This is the most complex discount - we need to divide the discount between rows based on their price in
* proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows
* with no price (free) don't get discounted.
*
* Get item discount by dividing item cost by subtotal to get a %
*/
$discount_percent = 0;
if ( WC()->cart->subtotal_ex_tax ) {
// Uses price inc tax if prices include tax to work around https://github.com/woothemes/woocommerce/issues/7669
$discount_percent = ( $cart_item['data']->get_price() * $cart_item['quantity'] ) / ( wc_prices_include_tax() ? WC()->cart->subtotal : WC()->cart->subtotal_ex_tax );
}
$discount = min( ( $this->coupon_amount * $discount_percent ) / $cart_item['quantity'], $discounting_amount );
} else {
$discount = min( $this->coupon_amount, $discounting_amount );
}
} elseif ( $this->is_type( 'fixed_product' ) ) {
$discount = min( $discount, $discounting_amount );
$discount = $single ? $discount : $discount * $cart_item_qty;
}
$discount = min( $discount, $discounting_amount );
// Handle the limit_usage_to_x_items option
if ( $this->is_type( array( 'percent_product', 'fixed_product' ) ) && ! is_null( $cart_item ) ) {
if ( $this->is_type( array( 'percent_product', 'fixed_product' ) ) ) {
if ( '' === $this->limit_usage_to_x_items ) {
$qty = $cart_item['quantity'];
$limit_usage_qty = $cart_item_qty;
} else {
$qty = min( $this->limit_usage_to_x_items, $cart_item['quantity'] );
$this->limit_usage_to_x_items = max( 0, $this->limit_usage_to_x_items - $qty );
$limit_usage_qty = min( $this->limit_usage_to_x_items, $cart_item_qty );
$this->limit_usage_to_x_items = max( 0, $this->limit_usage_to_x_items - $limit_usage_qty );
}
if ( $single ) {
$discount = ( $discount * $qty ) / $cart_item['quantity'];
$discount = ( $discount * $limit_usage_qty ) / $cart_item_qty;
} else {
$discount = ( $discount / $cart_item['quantity'] ) * $qty;
$discount = ( $discount / $cart_item_qty ) * $limit_usage_qty;
}
}
$discount = round( $discount, WC_ROUNDING_PRECISION );
return apply_filters( 'woocommerce_coupon_get_discount_amount', $discount, $discounting_amount, $cart_item, $single, $this );
}