Merge branch 'discount-rounding-mode'

This commit is contained in:
Mike Jolley 2015-04-10 11:06:53 +01:00
commit 2d99e060a1
4 changed files with 47 additions and 54 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') ) {
@ -1740,11 +1743,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 +1757,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 +1812,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 +2152,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 +2161,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 +2170,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 +2186,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( $this->coupon_amount, $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 );
}

View File

@ -199,7 +199,7 @@ class Coupon extends \WC_Unit_Test_Case {
update_post_meta( $coupon->id, 'discount_type', 'fixed_product' );
update_post_meta( $coupon->id, 'coupon_amount', '5' );
// Create a flat rate method
// Create a flat rate method - $10
\WC_Helper_Shipping::create_simple_flat_rate();
// We need this to have the calculate_totals() method calculate totals
@ -207,7 +207,7 @@ class Coupon extends \WC_Unit_Test_Case {
define( 'WOOCOMMERCE_CHECKOUT', true );
}
// Add fee
// Add fee - $10
\WC_Helper_Fee::add_cart_fee();
// Add product to cart

View File

@ -160,6 +160,7 @@ final class WooCommerce {
$this->define( 'WC_VERSION', $this->version );
$this->define( 'WOOCOMMERCE_VERSION', $this->version );
$this->define( 'WC_ROUNDING_PRECISION', 4 );
$this->define( 'WC_DISCOUNT_ROUNDING_MODE', 2 );
$this->define( 'WC_TAX_ROUNDING_MODE', 'yes' === get_option( 'woocommerce_prices_include_tax', 'no' ) ? 2 : 1 );
$this->define( 'WC_DELIMITER', '|' );
$this->define( 'WC_LOG_DIR', $upload_dir['basedir'] . '/wc-logs/' );