Tax rewrite to deal with coupons before tax calculations
Needs a lot of testing - esp to detect rounding errors.
This commit is contained in:
parent
de1d59a313
commit
fe5651fff5
|
@ -89,7 +89,7 @@ function woocommerce_admin_scripts() {
|
|||
|
||||
$woocommerce_witepanel_params = array(
|
||||
'remove_item_notice' => __("Remove this item? If you have previously reduced this item's stock, or this order was submitted by a customer, will need to manually restore the item's stock.", 'woothemes'),
|
||||
'cart_total' => __("Calc totals based on order items, discount amount, and shipping?", 'woothemes'),
|
||||
'cart_total' => __("Calculate totals based on order items, discount amount, and shipping? Note, you will need to calculate discounts before tax manually.", 'woothemes'),
|
||||
'copy_billing' => __("Copy billing information to shipping information? This will remove any currently entered shipping information.", 'woothemes'),
|
||||
'prices_include_tax' => get_option('woocommerce_prices_include_tax'),
|
||||
'ID' => __('ID', 'woothemes'),
|
||||
|
|
|
@ -35,6 +35,9 @@ function woocommerce_coupon_data_meta_box($post) {
|
|||
// Individual use
|
||||
woocommerce_wp_checkbox( array( 'id' => 'individual_use', 'label' => __('Individual use', 'woothemes'), 'description' => __('Check this box if the coupon cannot be used in conjunction with other coupons', 'woothemes') ) );
|
||||
|
||||
// Apply before tax
|
||||
woocommerce_wp_checkbox( array( 'id' => 'apply_before_tax', 'label' => __('Apply coupon before tax?', 'woothemes'), 'description' => __('Check this box if the coupon should be applied before calculating a product\'s tax', 'woothemes') ) );
|
||||
|
||||
// Product ids
|
||||
woocommerce_wp_text_input( array( 'id' => 'product_ids', 'label' => __('Product IDs', 'woothemes'), 'placeholder' => __('N/A', 'woothemes'), 'description' => __('(optional) Comma separate IDs which need to be in the cart to use this coupon or, for "Product Discounts", which products are discounted.', 'woothemes') ) );
|
||||
|
||||
|
@ -54,18 +57,6 @@ function woocommerce_coupon_data_meta_box($post) {
|
|||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Coupon data meta box
|
||||
*
|
||||
* Displays the meta box
|
||||
*/
|
||||
add_filter('enter_title_here', 'woocommerce_coupon_enter_title_here', 1, 2);
|
||||
|
||||
function woocommerce_coupon_enter_title_here( $text, $post ) {
|
||||
if ($post->post_type=='shop_coupon') return __('Coupon code', 'woothemes');
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coupon Data Save
|
||||
*
|
||||
|
@ -89,6 +80,7 @@ function woocommerce_process_shop_coupon_meta( $post_id, $post ) {
|
|||
$usage_limit = (isset($_POST['usage_limit']) && $_POST['usage_limit']>0) ? (int) $_POST['usage_limit'] : '';
|
||||
$individual_use = isset($_POST['individual_use']) ? 'yes' : 'no';
|
||||
$expiry_date = strip_tags(stripslashes( $_POST['expiry_date'] ));
|
||||
$apply_before_tax = isset($_POST['apply_before_tax']) ? 'yes' : 'no';
|
||||
|
||||
// Save
|
||||
update_post_meta( $post_id, 'discount_type', $type );
|
||||
|
@ -98,6 +90,7 @@ function woocommerce_process_shop_coupon_meta( $post_id, $post ) {
|
|||
update_post_meta( $post_id, 'exclude_product_ids', $exclude_product_ids );
|
||||
update_post_meta( $post_id, 'usage_limit', $usage_limit );
|
||||
update_post_meta( $post_id, 'expiry_date', $expiry_date );
|
||||
update_post_meta( $post_id, 'apply_before_tax', $apply_before_tax );
|
||||
|
||||
do_action('woocommerce_coupon_options');
|
||||
|
||||
|
|
|
@ -44,6 +44,17 @@ function woocommerce_meta_boxes() {
|
|||
add_meta_box('product_variation-parent', __('Product', 'woothemes'), 'variations_product_meta_box', 'product_variation', 'side', 'default');
|
||||
}
|
||||
|
||||
/**
|
||||
* Title boxes
|
||||
*/
|
||||
add_filter('enter_title_here', 'woocommerce_enter_title_here', 1, 2);
|
||||
|
||||
function woocommerce_enter_title_here( $text, $post ) {
|
||||
if ($post->post_type=='shop_coupon') return __('Coupon code', 'woothemes');
|
||||
if ($post->post_type=='product') return __('Product name', 'woothemes');
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let variations have a product as the parent
|
||||
*/
|
||||
|
|
|
@ -17,7 +17,6 @@ class woocommerce_cart {
|
|||
var $applied_coupons;
|
||||
|
||||
var $cart_contents_total;
|
||||
var $cart_contents_total_ex_tax;
|
||||
var $cart_contents_weight;
|
||||
var $cart_contents_count;
|
||||
var $cart_contents_tax;
|
||||
|
@ -26,14 +25,20 @@ class woocommerce_cart {
|
|||
var $subtotal;
|
||||
var $subtotal_ex_tax;
|
||||
var $tax_total;
|
||||
var $discount_product;
|
||||
var $discount_total;
|
||||
var $shipping_total;
|
||||
var $shipping_tax_total;
|
||||
|
||||
/* Private variables */
|
||||
var $tax;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function __construct() {
|
||||
$this->tax = &new woocommerce_tax();
|
||||
|
||||
add_action('init', array(&$this, 'init'), 1); // Get cart on init
|
||||
add_action('wp', array(&$this, 'calculate_totals'), 1); // Defer calculate totals so we can detect page
|
||||
}
|
||||
|
@ -106,18 +111,7 @@ class woocommerce_cart {
|
|||
*/
|
||||
function empty_cart() {
|
||||
$this->cart_contents = array();
|
||||
$this->total = 0;
|
||||
$this->cart_contents_total = 0;
|
||||
$this->cart_contents_total_ex_tax = 0;
|
||||
$this->cart_contents_weight = 0;
|
||||
$this->cart_contents_count = 0;
|
||||
$this->cart_contents_tax = 0;
|
||||
$this->tax_total = 0;
|
||||
$this->shipping_tax_total = 0;
|
||||
$this->subtotal = 0;
|
||||
$this->subtotal_ex_tax = 0;
|
||||
$this->discount_total = 0;
|
||||
$this->shipping_total = 0;
|
||||
$this->reset_totals();
|
||||
unset($_SESSION['cart']);
|
||||
unset($_SESSION['coupons']);
|
||||
}
|
||||
|
@ -188,8 +182,8 @@ class woocommerce_cart {
|
|||
$product_data = &new woocommerce_product( $product_id );
|
||||
endif;
|
||||
|
||||
// Type check
|
||||
if ( $product_data->is_type('external') ) :
|
||||
// Type/Exists check
|
||||
if ( $product_data->is_type('external') || !$product_data->exists() ) :
|
||||
$woocommerce->add_error( __('This product cannot be purchased.', 'woothemes') );
|
||||
return false;
|
||||
endif;
|
||||
|
@ -308,16 +302,11 @@ class woocommerce_cart {
|
|||
}
|
||||
|
||||
/**
|
||||
* calculate totals for the items in the cart
|
||||
* Reset totals
|
||||
*/
|
||||
function calculate_totals() {
|
||||
global $woocommerce;
|
||||
|
||||
$_tax = &new woocommerce_tax();
|
||||
|
||||
private function reset_totals() {
|
||||
$this->total = 0;
|
||||
$this->cart_contents_total = 0;
|
||||
$this->cart_contents_total_ex_tax = 0;
|
||||
$this->cart_contents_weight = 0;
|
||||
$this->cart_contents_count = 0;
|
||||
$this->cart_contents_tax = 0;
|
||||
|
@ -326,86 +315,128 @@ class woocommerce_cart {
|
|||
$this->subtotal = 0;
|
||||
$this->subtotal_ex_tax = 0;
|
||||
$this->discount_total = 0;
|
||||
$this->discount_product = 0;
|
||||
$this->shipping_total = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to apply discounts to a product and get the discounted price (before tax is applied)
|
||||
*/
|
||||
function get_discounted_price( $values, $price ) {
|
||||
|
||||
if (sizeof($this->cart_contents)>0) : foreach ($this->cart_contents as $cart_item_key => $values) :
|
||||
if ($this->applied_coupons) foreach ($this->applied_coupons as $code) :
|
||||
$coupon = &new woocommerce_coupon( $code );
|
||||
|
||||
// Get product from cart data
|
||||
$_product = $values['data'];
|
||||
if ( $coupon->apply_before_tax() && $coupon->is_valid() ) :
|
||||
|
||||
switch ($coupon->type) :
|
||||
|
||||
case "fixed_product" :
|
||||
case "percent_product" :
|
||||
|
||||
$this_item_is_discounted = false;
|
||||
|
||||
if ($_product->exists() && $values['quantity']>0) :
|
||||
|
||||
$this->cart_contents_count = $this->cart_contents_count + $values['quantity'];
|
||||
|
||||
$this->cart_contents_weight = $this->cart_contents_weight + ($_product->get_weight() * $values['quantity']);
|
||||
|
||||
$total_item_price = $_product->get_price() * $values['quantity'];
|
||||
|
||||
if ( get_option('woocommerce_calc_taxes')=='yes') :
|
||||
|
||||
if ( $_product->is_taxable() ) :
|
||||
|
||||
$rate = $_tax->get_rate( $_product->get_tax_class() );
|
||||
// Specific product ID's get the discount
|
||||
if (sizeof($coupon->product_ids)>0) :
|
||||
|
||||
if ((in_array($values['product_id'], $coupon->product_ids) || in_array($values['variation_id'], $coupon->product_ids))) :
|
||||
$this_item_is_discounted = true;
|
||||
endif;
|
||||
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes') :
|
||||
// Price incldues tax
|
||||
$tax_amount = $_tax->calc_tax( $_product->get_price(), $rate, true ) * $values['quantity'];
|
||||
else :
|
||||
// Price excludes tax
|
||||
$tax_amount = $_tax->calc_tax( $_product->get_price(), $rate, false ) * $values['quantity'];
|
||||
|
||||
// No product ids - all items discounted
|
||||
$this_item_is_discounted = true;
|
||||
|
||||
endif;
|
||||
|
||||
// Specific product ID's excluded from the discount
|
||||
if (sizeof($coupon->exclude_product_ids)>0) :
|
||||
|
||||
if ((in_array($values['product_id'], $coupon->exclude_product_ids) || in_array($values['variation_id'], $coupon->exclude_product_ids))) :
|
||||
$this_item_is_discounted = false;
|
||||
endif;
|
||||
|
||||
endif;
|
||||
|
||||
/**
|
||||
* Checkout calculations when customer is OUTSIDE the shop base country and price INCLUDE tax
|
||||
*/
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes' && $woocommerce->customer->is_customer_outside_base() && defined('WOOCOMMERCE_CHECKOUT') && WOOCOMMERCE_CHECKOUT ) :
|
||||
// Get the base rate first
|
||||
$base_rate = $_tax->get_shop_base_rate( $_product->tax_class );
|
||||
// Apply filter
|
||||
$this_item_is_discounted = apply_filters( 'woocommerce_item_is_discounted', $this_item_is_discounted, $values, $before_tax = true );
|
||||
|
||||
// Apply the discount
|
||||
if ($this_item_is_discounted) :
|
||||
if ($coupon->type=='fixed_product') :
|
||||
|
||||
// Calc tax for base country
|
||||
$base_tax_amount = $_tax->calc_tax( $_product->get_price(), $base_rate, true);
|
||||
|
||||
// Now calc tax for user county (which now excludes tax)
|
||||
$tax_amount = $_tax->calc_tax( ( $_product->get_price() - $base_tax_amount ), $rate, false );
|
||||
$tax_amount = $tax_amount * $values['quantity'];
|
||||
|
||||
// Finally, update $total_item_price to reflect tax amounts
|
||||
$total_item_price = ($total_item_price - ($base_tax_amount * $values['quantity']) + $tax_amount);
|
||||
|
||||
/**
|
||||
* Checkout calculations when customer is INSIDE the shop base country and price INCLUDE tax
|
||||
*/
|
||||
elseif (get_option('woocommerce_prices_include_tax')=='yes' && $_product->get_tax_class() !== $_product->tax_class) :
|
||||
|
||||
// Calc tax for original rate
|
||||
$original_tax_amount = $_tax->calc_tax( $_product->get_price(), $_tax->get_rate( $_product->tax_class ), true);
|
||||
|
||||
// Now calc tax for new rate (which now excludes tax)
|
||||
$tax_amount = $_tax->calc_tax( ( $_product->get_price() - $original_tax_amount ), $rate, false );
|
||||
$tax_amount = $tax_amount * $values['quantity'];
|
||||
|
||||
$total_item_price = ($total_item_price - ($original_tax_amount * $values['quantity']) + $tax_amount);
|
||||
$this->discount_product = $this->discount_product + ( $coupon->amount * $values['quantity'] );
|
||||
|
||||
$price = $price - $coupon->amount;
|
||||
|
||||
elseif ($coupon->type=='percent_product') :
|
||||
|
||||
$percent_discount = ( $values['data']->get_price_excluding_tax() / 100 ) * $coupon->amount;
|
||||
|
||||
$this->discount_product = $this->discount_product + ( $percent_discount * $values['quantity'] );
|
||||
|
||||
$price = $price - $percent_discount;
|
||||
|
||||
endif;
|
||||
endif;
|
||||
|
||||
endif;
|
||||
break;
|
||||
|
||||
endif;
|
||||
case "fixed_cart" :
|
||||
|
||||
$tax_amount = ( isset($tax_amount) ? $tax_amount : 0 );
|
||||
|
||||
$this->cart_contents_tax = $this->cart_contents_tax + $tax_amount;
|
||||
$this->cart_contents_total = $this->cart_contents_total + $total_item_price;
|
||||
$this->cart_contents_total_ex_tax = $this->cart_contents_total_ex_tax + ($_product->get_price_excluding_tax()*$values['quantity']);
|
||||
|
||||
// Product Discounts
|
||||
if ($this->applied_coupons) foreach ($this->applied_coupons as $code) :
|
||||
$coupon = &new woocommerce_coupon( $code );
|
||||
// Use pence to help prevent rounding errors
|
||||
$coupon_amount_pence = $coupon->amount * 100;
|
||||
|
||||
// Get item discount by dividing by total number of products in the cart
|
||||
$item_discount = $coupon_amount_pence / $this->cart_contents_count;
|
||||
|
||||
// Take discount off of price (in pence)
|
||||
$price = ( $price * 100 ) - $item_discount;
|
||||
|
||||
// Back to pounds
|
||||
$price = $price / 100;
|
||||
|
||||
// Add coupon to discount total (once, since this is a fixed cart discount and we don't want rounding issues)
|
||||
$this->discount_product = $this->discount_product + (($item_discount*$values['quantity']) / 100);
|
||||
|
||||
break;
|
||||
|
||||
if ($coupon->type!='fixed_product' && $coupon->type!='percent_product') continue;
|
||||
case "percent" :
|
||||
|
||||
// Get % off each item - this works out the same as doing the whole cart
|
||||
$percent_discount = ( $values['data']->get_price_excluding_tax() / 100 ) * $coupon->amount;
|
||||
|
||||
$this->discount_product = $this->discount_product + ( $percent_discount * $values['quantity'] );
|
||||
|
||||
$price = $price - $percent_discount;
|
||||
|
||||
break;
|
||||
|
||||
endswitch;
|
||||
|
||||
endif;
|
||||
endforeach;
|
||||
|
||||
return $price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to apply product discounts after tax
|
||||
*/
|
||||
function apply_discount_products_after_tax( $total_item_price ) {
|
||||
|
||||
if ($this->applied_coupons) foreach ($this->applied_coupons as $code) :
|
||||
$coupon = &new woocommerce_coupon( $code );
|
||||
|
||||
if ($coupon->type!='fixed_product' && $coupon->type!='percent_product') continue;
|
||||
|
||||
if ( !$coupon->apply_before_tax() && $coupon->is_valid() ) :
|
||||
|
||||
if (sizeof($this->cart_contents)>0) foreach ($this->cart_contents as $cart_item_key => $values) :
|
||||
|
||||
$this_item_is_discounted = false;
|
||||
|
||||
|
||||
// Specific product ID's get the discount
|
||||
if (sizeof($coupon->product_ids)>0) :
|
||||
|
||||
|
@ -419,7 +450,7 @@ class woocommerce_cart {
|
|||
$this_item_is_discounted = true;
|
||||
|
||||
endif;
|
||||
|
||||
|
||||
// Specific product ID's excluded from the discount
|
||||
if (sizeof($coupon->exclude_product_ids)>0) :
|
||||
|
||||
|
@ -430,7 +461,7 @@ class woocommerce_cart {
|
|||
endif;
|
||||
|
||||
// Apply filter
|
||||
$this_item_is_discounted = apply_filters( 'woocommerce_item_is_discounted', $this_item_is_discounted, $values );
|
||||
$this_item_is_discounted = apply_filters( 'woocommerce_item_is_discounted', $this_item_is_discounted, $values, $before_tax = false );
|
||||
|
||||
// Apply the discount
|
||||
if ($this_item_is_discounted) :
|
||||
|
@ -440,65 +471,143 @@ class woocommerce_cart {
|
|||
$this->discount_total = $this->discount_total + ( $total_item_price / 100 ) * $coupon->amount;
|
||||
endif;
|
||||
endif;
|
||||
|
||||
|
||||
endforeach;
|
||||
|
||||
endif;
|
||||
endforeach; endif;
|
||||
endforeach;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to apply cart discounts after tax
|
||||
*/
|
||||
function apply_cart_discounts_after_tax() {
|
||||
|
||||
// Calculate final totals
|
||||
$this->tax_total = $this->cart_contents_tax; // Tax Total
|
||||
$this->subtotal_ex_tax = $this->cart_contents_total_ex_tax; // Subtotal without tax
|
||||
$this->subtotal = $this->cart_contents_total; // Subtotal
|
||||
if ($this->applied_coupons) foreach ($this->applied_coupons as $code) :
|
||||
$coupon = &new woocommerce_coupon( $code );
|
||||
|
||||
if ( !$coupon->apply_before_tax() && $coupon->is_valid() ) :
|
||||
|
||||
switch ($coupon->type) :
|
||||
|
||||
case "fixed_cart" :
|
||||
|
||||
$this->discount_total = $this->discount_total + $coupon->amount;
|
||||
|
||||
break;
|
||||
|
||||
case "percent" :
|
||||
|
||||
$percent_discount = round( ( ($this->cart_contents_total + $this->tax_total) / 100) * $coupon->amount , 2);
|
||||
|
||||
$this->discount_total = $this->discount_total + $percent_discount;
|
||||
|
||||
break;
|
||||
|
||||
endswitch;
|
||||
|
||||
endif;
|
||||
endforeach;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate totals for the items in the cart
|
||||
*/
|
||||
function calculate_totals() {
|
||||
global $woocommerce;
|
||||
|
||||
$this->reset_totals();
|
||||
|
||||
// Get count of all items
|
||||
if (sizeof($this->cart_contents)>0) foreach ($this->cart_contents as $cart_item_key => $values) $this->cart_contents_count = $this->cart_contents_count + $values['quantity'];
|
||||
|
||||
// Calc totals for items
|
||||
if (sizeof($this->cart_contents)>0) foreach ($this->cart_contents as $cart_item_key => $values) :
|
||||
|
||||
$_product = $values['data'];
|
||||
|
||||
$this->cart_contents_weight = $this->cart_contents_weight + ($_product->get_weight() * $values['quantity']);
|
||||
|
||||
// Base Price (i.e. no tax, regardless of region)
|
||||
$base_price = $_product->get_price_excluding_tax();
|
||||
|
||||
// Discounted Price (base price with any pre-tax discounts applied
|
||||
$discounted_price = $this->get_discounted_price( $values, $base_price );
|
||||
|
||||
// Tax Amount (For the line, based on discounted, ex.tax price)
|
||||
if ( get_option('woocommerce_calc_taxes')=='yes' && $_product->is_taxable() ) :
|
||||
|
||||
$tax_rate = $this->tax->get_rate( $_product->get_tax_class() );
|
||||
$tax_amount = $this->tax->calc_tax( $base_price, $tax_rate, false ) * $values['quantity'];
|
||||
$discounted_tax_amount = $this->tax->calc_tax( $discounted_price, $tax_rate, false ) * $values['quantity'];
|
||||
|
||||
else :
|
||||
|
||||
$tax_amount = 0;
|
||||
$discounted_tax_amount = 0;
|
||||
|
||||
endif;
|
||||
|
||||
// Total item price (discounted price + tax * quantity)
|
||||
$total_item_price = ($discounted_price*$values['quantity']) + $discounted_tax_amount;
|
||||
|
||||
// Add any product discounts (after tax)
|
||||
$this->apply_discount_products_after_tax( $total_item_price );
|
||||
|
||||
// Sub total is based on base prices (without discounts)
|
||||
$this->subtotal = $this->subtotal + ($base_price*$values['quantity']) + $tax_amount;
|
||||
$this->subtotal_ex_tax = $this->subtotal_ex_tax + ($base_price*$values['quantity']);
|
||||
|
||||
// Cart contents total is based on discounted prices and is used for the final total calculation
|
||||
$this->cart_contents_total = $this->cart_contents_total + ($discounted_price*$values['quantity']);
|
||||
|
||||
// Cart tax is based on discounted amounts
|
||||
$this->tax_total = $this->tax_total + $discounted_tax_amount;
|
||||
|
||||
endforeach;
|
||||
|
||||
// Cart Discounts (after tax)
|
||||
$this->apply_cart_discounts_after_tax();
|
||||
|
||||
// Only go beyond this point if on the cart/checkout
|
||||
if (!is_checkout() && !is_cart() && !defined('WOOCOMMERCE_CHECKOUT') && !is_ajax()) return;
|
||||
|
||||
// Cart Discounts
|
||||
if ($this->applied_coupons) foreach ($this->applied_coupons as $code) :
|
||||
$coupon = &new woocommerce_coupon( $code );
|
||||
if ($coupon->is_valid()) :
|
||||
if ($coupon->type=='fixed_cart') :
|
||||
|
||||
$this->discount_total = $this->discount_total + $coupon->amount;
|
||||
|
||||
elseif ($coupon->type=='percent') :
|
||||
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes') :
|
||||
$this->discount_total = $this->discount_total + ( $this->subtotal / 100 ) * $coupon->amount;
|
||||
else :
|
||||
$this->discount_total = $this->discount_total + ( ($this->subtotal + $this->cart_contents_tax) / 100 ) * $coupon->amount;
|
||||
endif;
|
||||
|
||||
endif;
|
||||
endif;
|
||||
endforeach;
|
||||
|
||||
// Cart Shipping
|
||||
if ($this->needs_shipping()) $woocommerce->shipping->calculate_shipping(); else $woocommerce->shipping->reset_shipping();
|
||||
if ($this->needs_shipping()) :
|
||||
$woocommerce->shipping->calculate_shipping();
|
||||
else :
|
||||
$woocommerce->shipping->reset_shipping();
|
||||
endif;
|
||||
|
||||
$this->shipping_total = $woocommerce->shipping->shipping_total; // Shipping Total
|
||||
$this->shipping_tax_total = $woocommerce->shipping->shipping_tax; // Shipping Tax
|
||||
|
||||
// VAT excemption done at this point - so all totals are correct before exemption
|
||||
if ($woocommerce->customer->is_vat_exempt()) :
|
||||
$this->shipping_tax_total = 0;
|
||||
$this->tax_total = 0;
|
||||
$this->shipping_tax_total = $this->tax_total = 0;
|
||||
endif;
|
||||
|
||||
// Allow plugins to hook and alter totals before final total is calculated
|
||||
do_action('woocommerce_calculate_totals', $this);
|
||||
|
||||
// Grand Total
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes') :
|
||||
$this->total = $this->subtotal + $this->shipping_tax_total - $this->discount_total + $woocommerce->shipping->shipping_total;
|
||||
else :
|
||||
$this->total = $this->subtotal + $this->tax_total + $this->shipping_tax_total - $this->discount_total + $woocommerce->shipping->shipping_total;
|
||||
endif;
|
||||
/**
|
||||
* Grand Total
|
||||
*
|
||||
* Based on discounted product prices, discounted tax, shipping cost + tax, and any discounts to be added after tax (e.g. store credit)
|
||||
*/
|
||||
$this->total = $this->cart_contents_total + $this->tax_total + $this->shipping_tax_total + $woocommerce->shipping->shipping_total - $this->discount_total;
|
||||
|
||||
if ($this->total < 0) $this->total = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the total of all discounts
|
||||
*/
|
||||
function get_discount_total() {
|
||||
return $this->discount_total + $this->discount_product;
|
||||
}
|
||||
|
||||
/**
|
||||
*returns whether or not a discount has been applied
|
||||
*/
|
||||
|
@ -547,10 +656,10 @@ class woocommerce_cart {
|
|||
* Check cart items for errors
|
||||
*/
|
||||
function check_cart_items() {
|
||||
|
||||
global $woocommerce;
|
||||
|
||||
$result = $this->check_cart_item_stock();
|
||||
if (is_wp_error($result)) $woocommerce->add_error( $result->get_error_message() );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -720,11 +829,7 @@ class woocommerce_cart {
|
|||
|
||||
if (get_option('woocommerce_display_totals_tax')=='excluding' || ( defined('WOOCOMMERCE_CHECKOUT') && WOOCOMMERCE_CHECKOUT )) :
|
||||
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes') :
|
||||
$return = woocommerce_price($this->subtotal - $this->tax_total);
|
||||
else :
|
||||
$return = woocommerce_price($this->subtotal);
|
||||
endif;
|
||||
$return = woocommerce_price( $this->subtotal_ex_tax );
|
||||
|
||||
if ($this->tax_total>0) :
|
||||
$return .= ' <small>'.$woocommerce->countries->ex_tax_or_vat().'</small>';
|
||||
|
@ -733,11 +838,7 @@ class woocommerce_cart {
|
|||
|
||||
else :
|
||||
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes') :
|
||||
$return = woocommerce_price($this->subtotal);
|
||||
else :
|
||||
$return = woocommerce_price($this->subtotal + $this->tax_total);
|
||||
endif;
|
||||
$return = woocommerce_price( $this->subtotal );
|
||||
|
||||
if ($this->tax_total>0) :
|
||||
$return .= ' <small>'.$woocommerce->countries->inc_tax_or_vat().'</small>';
|
||||
|
@ -802,10 +903,34 @@ class woocommerce_cart {
|
|||
}
|
||||
|
||||
/**
|
||||
* gets the total discount amount
|
||||
* gets the total (product) discount amount - these are applied before tax
|
||||
*/
|
||||
function get_discounts_before_tax() {
|
||||
if ($this->discount_product) :
|
||||
return woocommerce_price($this->discount_product);
|
||||
endif;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the total (product) discount amount - these are applied before tax
|
||||
*/
|
||||
function get_discounts_after_tax() {
|
||||
if ($this->discount_total) :
|
||||
return woocommerce_price($this->discount_total);
|
||||
endif;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gets the total discount amount - both kinds
|
||||
*/
|
||||
function get_total_discount() {
|
||||
if ($this->discount_total) return woocommerce_price($this->discount_total); else return false;
|
||||
if ($this->discount_total || $this->discount_product) :
|
||||
return woocommerce_price($this->discount_total + $this->discount_product);
|
||||
endif;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -745,7 +745,7 @@ class woocommerce_checkout {
|
|||
update_post_meta( $order_id, '_payment_method', $this->posted['payment_method']);
|
||||
update_post_meta( $order_id, '_order_subtotal', number_format($woocommerce->cart->subtotal_ex_tax, 2, '.', ''));
|
||||
update_post_meta( $order_id, '_order_shipping', number_format($woocommerce->cart->shipping_total, 2, '.', ''));
|
||||
update_post_meta( $order_id, '_order_discount', number_format($woocommerce->cart->discount_total, 2, '.', ''));
|
||||
update_post_meta( $order_id, '_order_discount', number_format($woocommerce->cart->get_discount_total(), 2, '.', ''));
|
||||
update_post_meta( $order_id, '_order_tax', number_format($woocommerce->cart->tax_total, 2, '.', ''));
|
||||
update_post_meta( $order_id, '_order_shipping_tax', number_format($woocommerce->cart->shipping_tax_total, 2, '.', ''));
|
||||
update_post_meta( $order_id, '_order_total', number_format($woocommerce->cart->total, 2, '.', ''));
|
||||
|
|
|
@ -20,6 +20,7 @@ class woocommerce_coupon {
|
|||
var $usage_limit;
|
||||
var $usage_count;
|
||||
var $expiry_date;
|
||||
var $apply_before_tax;
|
||||
|
||||
/** get coupon with $code */
|
||||
function woocommerce_coupon( $code ) {
|
||||
|
@ -39,6 +40,7 @@ class woocommerce_coupon {
|
|||
$this->usage_limit = get_post_meta($coupon->ID, 'usage_limit', true);
|
||||
$this->usage_count = (int) get_post_meta($coupon->ID, 'usage_count', true);
|
||||
$this->expiry_date = ($expires = get_post_meta($coupon->ID, 'expiry_date', true)) ? strtotime($expires) : '';
|
||||
$this->apply_before_tax = get_post_meta($coupon->ID, 'apply_before_tax', true);
|
||||
|
||||
if (!$this->amount) return false;
|
||||
|
||||
|
@ -49,6 +51,11 @@ class woocommerce_coupon {
|
|||
return false;
|
||||
}
|
||||
|
||||
/** Check if coupon needs applying before tax **/
|
||||
function apply_before_tax() {
|
||||
if ($this->apply_before_tax=='yes') return true; else return false;
|
||||
}
|
||||
|
||||
/** Increase usage count */
|
||||
function inc_usage_count() {
|
||||
$this->usage_count++;
|
||||
|
|
|
@ -166,7 +166,6 @@ class woocommerce_paypal extends woocommerce_payment_gateway {
|
|||
'upload' => 1,
|
||||
'return' => $this->get_return_url( $order ),
|
||||
'cancel_return' => $order->get_cancel_order_url(),
|
||||
//'cancel_return' => home_url(),
|
||||
|
||||
// Order key
|
||||
'custom' => $order_id,
|
||||
|
@ -189,7 +188,7 @@ class woocommerce_paypal extends woocommerce_payment_gateway {
|
|||
// Payment Info
|
||||
'invoice' => $order->order_key,
|
||||
'tax_cart' => $order->get_total_tax(),
|
||||
'discount_amount_cart' => $order->order_discount
|
||||
'discount_amount_cart' => $order->get_total_discount()
|
||||
),
|
||||
$phone_args
|
||||
);
|
||||
|
|
|
@ -145,11 +145,19 @@ class woocommerce_order {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/** Gets shipping and product tax */
|
||||
function get_total_tax() {
|
||||
return $this->order_tax + $this->order_shipping_tax;
|
||||
}
|
||||
|
||||
|
||||
/** Gets total discount */
|
||||
function get_total_discount() {
|
||||
return $this->order_discount;
|
||||
}
|
||||
|
||||
|
||||
/** Gets subtotal */
|
||||
function get_subtotal_to_display() {
|
||||
global $woocommerce;
|
||||
|
|
|
@ -505,7 +505,7 @@ class woocommerce_product {
|
|||
|
||||
// Round
|
||||
$price = round( $price * 100 ) / 100;
|
||||
|
||||
|
||||
// Format
|
||||
$price = number_format($price, 2, '.', '');
|
||||
|
||||
|
|
|
@ -235,21 +235,24 @@ class woocommerce_tax {
|
|||
*/
|
||||
function calc_tax( $price, $rate, $price_includes_tax = true ) {
|
||||
|
||||
$price = round($price * 100, 0); // To avoid float rounding errors, work with integers (pence)
|
||||
|
||||
$price = round($price * 10000, 0); // To avoid float rounding errors, work with integers (pence + 2 dp = 4 decimals)
|
||||
$rate = $rate * 100;
|
||||
|
||||
if ($price_includes_tax) :
|
||||
|
||||
$rate = ($rate / 100) + 1;
|
||||
$rate = ($rate / 10000) + 1;
|
||||
$tax_amount = $price - ( $price / $rate);
|
||||
|
||||
else :
|
||||
$tax_amount = $price * ($rate/100);
|
||||
$tax_amount = $price * ($rate/10000);
|
||||
endif;
|
||||
|
||||
$tax_amount = round($tax_amount); // Round to the nearest pence
|
||||
$tax_amount = $tax_amount / 100; // Back to pounds
|
||||
$tax_amount = round($tax_amount, 0); // Round to the nearest pence
|
||||
$tax_amount = $tax_amount / 10000; // Back to pounds
|
||||
|
||||
return number_format($tax_amount, 2, '.', '');
|
||||
return $tax_amount;
|
||||
|
||||
//return number_format($tax_amount, 2, '.', '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,8 +82,11 @@ Yes you can! Join in on our GitHub repository :) https://github.com/woothemes/wo
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= 1.2.5 - 18/11/2011 =
|
||||
= 1.3 - 18/11/2011 =
|
||||
* Schema.org markup for products and reviews
|
||||
* Option to apply coupons before tax
|
||||
* Rewritten cart calculations to support coupons before tax and after tax (optional)
|
||||
* 2 lines of discounts on total tables - 1 for product discounts, 1 for after tax discounts (e.g. store credit)
|
||||
|
||||
= 1.2.4 - 18/11/2011 =
|
||||
* More sale price logic fixes for variations. Now correctly compares variation's prices.
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
<td><?php echo $woocommerce->cart->get_cart_subtotal(); ?></td>
|
||||
</tr>
|
||||
|
||||
<?php if ($woocommerce->cart->get_discounts_before_tax()) : ?><tr class="discount">
|
||||
<td colspan="2"><?php _e('Product Discounts', 'woothemes'); ?></td>
|
||||
<td>-<?php echo $woocommerce->cart->get_discounts_before_tax(); ?></td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
<?php if ($woocommerce->cart->needs_shipping()) : ?>
|
||||
<td colspan="2"><?php _e('Shipping', 'woothemes'); ?></td>
|
||||
<td>
|
||||
|
@ -66,10 +71,11 @@
|
|||
<td><?php echo $woocommerce->cart->get_cart_tax(); ?></td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
<?php if ($woocommerce->cart->get_total_discount()) : ?><tr class="discount">
|
||||
<?php if ($woocommerce->cart->get_discounts_after_tax()) : ?><tr class="discount">
|
||||
<td colspan="2"><?php _e('Discount', 'woothemes'); ?></td>
|
||||
<td>-<?php echo $woocommerce->cart->get_total_discount(); ?></td>
|
||||
<td>-<?php echo $woocommerce->cart->get_discounts_after_tax(); ?></td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
<tr>
|
||||
<td colspan="2"><strong><?php _e('Grand Total', 'woothemes'); ?></strong></td>
|
||||
<td><strong><?php echo $woocommerce->cart->get_total(); ?></strong></td>
|
||||
|
|
|
@ -730,6 +730,11 @@ if (!function_exists('woocommerce_cart_totals')) {
|
|||
<td><?php echo $woocommerce->cart->get_cart_subtotal(); ?></td>
|
||||
</tr>
|
||||
|
||||
<?php if ($woocommerce->cart->get_discounts_before_tax()) : ?><tr class="discount">
|
||||
<th><?php _e('Product Discounts', 'woothemes'); ?></th>
|
||||
<td>-<?php echo $woocommerce->cart->get_discounts_before_tax(); ?></td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
<?php if ($woocommerce->cart->get_cart_shipping_total()) : ?><tr>
|
||||
<th><?php _e('Shipping', 'woothemes'); ?> <small><?php echo $woocommerce->countries->shipping_to_prefix().' '.__($woocommerce->countries->countries[ $woocommerce->customer->get_shipping_country() ], 'woothemes'); ?></small></th>
|
||||
<td>
|
||||
|
@ -772,7 +777,7 @@ if (!function_exists('woocommerce_cart_totals')) {
|
|||
?>
|
||||
</td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
|
||||
<?php if ($woocommerce->cart->get_cart_tax()) : ?><tr>
|
||||
<th><?php _e('Tax', 'woothemes'); ?> <?php if ($woocommerce->customer->is_customer_outside_base()) : ?><small><?php echo sprintf(__('estimated for %s', 'woothemes'), $woocommerce->countries->estimated_for_prefix() . __($woocommerce->countries->countries[ $woocommerce->countries->get_base_country() ], 'woothemes') ); ?></small><?php endif; ?></th>
|
||||
<td><?php
|
||||
|
@ -780,10 +785,11 @@ if (!function_exists('woocommerce_cart_totals')) {
|
|||
?></td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
<?php if ($woocommerce->cart->get_total_discount()) : ?><tr class="discount">
|
||||
<?php if ($woocommerce->cart->get_discounts_after_tax()) : ?><tr class="discount">
|
||||
<th><?php _e('Discount', 'woothemes'); ?></th>
|
||||
<td>-<?php echo $woocommerce->cart->get_total_discount(); ?></td>
|
||||
<td>-<?php echo $woocommerce->cart->get_discounts_after_tax(); ?></td>
|
||||
</tr><?php endif; ?>
|
||||
|
||||
<tr>
|
||||
<th><strong><?php _e('Total', 'woothemes'); ?></strong></th>
|
||||
<td><strong><?php echo $woocommerce->cart->get_total(); ?></strong></td>
|
||||
|
|
Loading…
Reference in New Issue