Final tax logic fixes
Storing base cost/discounted cost instead of row_discount to keep calks simple and maintain backwards compatibility.
This commit is contained in:
parent
4f9dc2335f
commit
6dc4d2add8
|
@ -731,7 +731,7 @@ $woocommerce_settings['tax'] = apply_filters('woocommerce_tax_settings', array(
|
|||
),
|
||||
|
||||
array(
|
||||
'name' => __( 'Frontend Tax display', 'woothemes' ),
|
||||
'name' => __( 'Tax display (cart totals)', 'woothemes' ),
|
||||
'desc' => __( 'Always display cart contents excluding tax', 'woothemes' ),
|
||||
'id' => 'woocommerce_display_cart_prices_excluding_tax',
|
||||
'std' => 'yes',
|
||||
|
|
|
@ -168,8 +168,8 @@ function woocommerce_order_items_meta_box($post) {
|
|||
<th class="meta" width="1%"><?php _e('Item Meta', 'woothemes'); ?></th>
|
||||
<?php do_action('woocommerce_admin_order_item_headers'); ?>
|
||||
<th class="quantity"><?php _e('Quantity', 'woothemes'); ?></th>
|
||||
<th class="cost"><?php _e('Cost', 'woothemes'); ?> <?php echo $woocommerce->countries->ex_tax_or_vat(); ?></th>
|
||||
<th class="cost"><?php _e('Row Discount', 'woothemes'); ?></th>
|
||||
<th class="cost"><?php _e('Base Cost', 'woothemes'); ?> <a class="tips" tip="<?php _e('Cost before discounts', 'woothemes'); ?> <?php echo $woocommerce->countries->ex_tax_or_vat(); ?>" href="#">[?]</a></th>
|
||||
<th class="cost"><?php _e('Cost', 'woothemes'); ?> <a class="tips" tip="<?php _e('Final cost after discount', 'woothemes'); ?> <?php echo $woocommerce->countries->ex_tax_or_vat(); ?>" href="#">[?]</a></th>
|
||||
<th class="tax"><?php _e('Tax Rate', 'woothemes'); ?></th>
|
||||
<th class="center" width="1%"><?php _e('Remove', 'woothemes'); ?></th>
|
||||
</tr>
|
||||
|
@ -235,11 +235,11 @@ function woocommerce_order_items_meta_box($post) {
|
|||
</td>
|
||||
|
||||
<td class="cost">
|
||||
<input type="text" name="item_cost[<?php echo $loop; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" value="<?php echo esc_attr( $item['cost'] ); ?>" />
|
||||
<input type="text" name="base_item_cost[<?php echo $loop; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" value="<?php if (isset($item['base_cost'])) echo esc_attr( $item['base_cost'] ); else echo esc_attr( $item['cost'] ); ?>" />
|
||||
</td>
|
||||
|
||||
<td class="discount">
|
||||
<input type="text" name="item_discount[<?php echo $loop; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" value="<?php if (isset($item['row_discount'])) echo esc_attr( $item['row_discount'] ); ?>" />
|
||||
<td class="cost">
|
||||
<input type="text" name="item_cost[<?php echo $loop; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" value="<?php echo esc_attr( $item['cost'] ); ?>" />
|
||||
</td>
|
||||
|
||||
<td class="tax">
|
||||
|
@ -470,7 +470,7 @@ function woocommerce_process_shop_order_meta( $post_id, $post ) {
|
|||
$item_name = $_POST['item_name'];
|
||||
$item_quantity = $_POST['item_quantity'];
|
||||
$item_cost = $_POST['item_cost'];
|
||||
$item_discount = $_POST['item_discount'];
|
||||
$base_item_cost = $_POST['base_item_cost'];
|
||||
$item_tax_rate = $_POST['item_tax_rate'];
|
||||
$item_meta_names = $_POST['meta_name'];
|
||||
$item_meta_values = $_POST['meta_value'];
|
||||
|
@ -502,8 +502,8 @@ function woocommerce_process_shop_order_meta( $post_id, $post ) {
|
|||
'variation_id' => (int) $item_variation[$i],
|
||||
'name' => htmlspecialchars(stripslashes($item_name[$i])),
|
||||
'qty' => (int) $item_quantity[$i],
|
||||
'cost' => woocommerce_clean($item_cost[$i]),
|
||||
'row_discount' => number_format(woocommerce_clean($item_discount[$i]), 4, '.', ''),
|
||||
'cost' => number_format(woocommerce_clean($item_cost[$i]), 4, '.', ''),
|
||||
'base_cost' => number_format(woocommerce_clean($base_item_cost[$i]), 4, '.', ''),
|
||||
'taxrate' => number_format(woocommerce_clean($item_tax_rate[$i]), 4, '.', ''),
|
||||
'item_meta' => $item_meta->meta
|
||||
));
|
||||
|
|
|
@ -69,75 +69,65 @@ jQuery( function($){
|
|||
|
||||
itemCost = $('input[name^=item_cost]:eq(' + i + ')').val();
|
||||
itemQty = parseInt($('input[name^=item_quantity]:eq(' + i + ')').val());
|
||||
itemDiscount = $('input[name^=item_discount]:eq(' + i + ')').val();
|
||||
itemBase = $('input[name^=base_item_cost]:eq(' + i + ')').val();
|
||||
itemTax = $('input[name^=item_tax_rate]:eq(' + i + ')').val();
|
||||
|
||||
if (!itemCost) itemCost = 0;
|
||||
if (!itemTax) itemTax = 0;
|
||||
if (!itemQty) itemQty = 0;
|
||||
if (!itemDiscount) itemDiscount = 0;
|
||||
if (!itemBase) itemBase = 0;
|
||||
|
||||
totalItemTax = 0;
|
||||
|
||||
// Calculate tax and discounts
|
||||
cart_discount = cart_discount + parseFloat( itemDiscount );
|
||||
|
||||
if (itemTax && itemTax>0) {
|
||||
|
||||
if (woocommerce_writepanel_params.prices_include_tax == 'yes') {
|
||||
|
||||
taxRate = ( itemTax/100 ) + 1;
|
||||
|
||||
// Discount worked out from tax inc. price then tax worked out backwards
|
||||
price_in_tax = ( itemCost * taxRate );
|
||||
itemDiscount = (( itemBase * itemQty ) * taxRate) - (( itemCost * itemQty ) * taxRate);
|
||||
|
||||
discounted_price = ( price_in_tax * itemQty ) - itemDiscount;
|
||||
// Tax worked out backwards
|
||||
totalItemTax = (itemCost * itemQty) * ( itemTax/100 );
|
||||
|
||||
// Total item tax (after discount)
|
||||
totalItemTax = ( discounted_price - ( discounted_price / taxRate ) );
|
||||
discounted_price = (itemCost * itemQty) * taxRate;
|
||||
|
||||
if (woocommerce_writepanel_params.round_at_subtotal == 'no') {
|
||||
|
||||
totalItemTax = totalItemTax * 100;
|
||||
totalItemTax = totalItemTax.toFixed(2);
|
||||
totalItemTax = Math.round( totalItemTax ) / 100;
|
||||
|
||||
}
|
||||
|
||||
discounted_price = discounted_price - totalItemTax;
|
||||
|
||||
subtotal = subtotal + parseFloat( (itemCost * itemQty) );
|
||||
|
||||
} else {
|
||||
|
||||
taxRate = ( itemTax/100 );
|
||||
|
||||
// Discount worked out from ex. price and tax worked out forwards
|
||||
discounted_price = (itemCost * itemQty) - itemDiscount;
|
||||
|
||||
totalItemTax = ( discounted_price * taxRate );
|
||||
itemDiscount = ( itemBase * itemQty ) - ( itemCost * itemQty );
|
||||
|
||||
// Tax worked out forwards
|
||||
totalItemTax = (itemCost * itemQty) * taxRate;
|
||||
|
||||
discounted_price = (itemCost * itemQty) + totalItemTax;
|
||||
|
||||
if (woocommerce_writepanel_params.round_at_subtotal == 'no') {
|
||||
|
||||
totalItemTax = totalItemTax * 100;
|
||||
totalItemTax = totalItemTax.toFixed(2);
|
||||
totalItemTax = Math.round( totalItemTax ) / 100;
|
||||
|
||||
}
|
||||
|
||||
subtotal = subtotal + parseFloat( (itemCost * itemQty) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
discounted_price = (itemCost * itemQty ) - itemDiscount;
|
||||
|
||||
subtotal = subtotal + parseFloat( (itemCost*itemQty) );
|
||||
|
||||
itemDiscount = ( itemBase * itemQty ) - ( itemCost * itemQty );
|
||||
discounted_price = ( itemCost * itemQty );
|
||||
}
|
||||
|
||||
subtotal = subtotal + parseFloat( (itemBase * itemQty) );
|
||||
|
||||
cart_discount = cart_discount + parseFloat( itemDiscount );
|
||||
|
||||
totalItemCost = parseFloat( discounted_price );
|
||||
|
||||
itemTotal = itemTotal + parseFloat( totalItemCost );
|
||||
|
@ -155,7 +145,7 @@ jQuery( function($){
|
|||
|
||||
}
|
||||
|
||||
total = parseFloat(itemTotal) + parseFloat(tax) - parseFloat(discount) + parseFloat(shipping) + parseFloat(shipping_tax);
|
||||
total = parseFloat(itemTotal) - parseFloat(discount) + parseFloat(shipping) + parseFloat(shipping_tax);
|
||||
|
||||
// Rounding
|
||||
subtotal = subtotal * 100;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -686,15 +686,20 @@ class woocommerce_checkout {
|
|||
endforeach;
|
||||
endif;
|
||||
|
||||
// Calculate discounted price ex. vat
|
||||
if (get_option('woocommerce_prices_include_tax')=='yes') :
|
||||
$cost = $woocommerce->cart->get_discounted_price( $values, $_product->get_price() ) / (($rate/100) + 1);
|
||||
else :
|
||||
$cost = $woocommerce->cart->get_discounted_price( $values, $_product->get_price() );
|
||||
endif;
|
||||
|
||||
$order_items[] = apply_filters('new_order_item', array(
|
||||
'id' => $values['product_id'],
|
||||
'variation_id' => $values['variation_id'],
|
||||
'name' => $_product->get_title(),
|
||||
'qty' => (int) $values['quantity'],
|
||||
'cost' => $_product->get_price_excluding_tax( false ),
|
||||
'row_discount' => number_format(
|
||||
( ( $_product->get_price()-$woocommerce->cart->get_discounted_price( $values, $_product->get_price() ) ) * $values['quantity'] )
|
||||
, 4, '.', '' ),
|
||||
'base_cost' => $_product->get_price_excluding_tax( false ),
|
||||
'cost' => trim(trim(number_format($cost, 4, '.', ''), '0'), '.'),
|
||||
'taxrate' => $rate,
|
||||
'item_meta' => $item_meta->meta
|
||||
), $values);
|
||||
|
|
|
@ -190,37 +190,19 @@ class woocommerce_order {
|
|||
|
||||
/** Calculate item cost - useful for gateways */
|
||||
function get_item_cost( $item, $inc_tax = false ) {
|
||||
|
||||
if ($inc_tax) :
|
||||
|
||||
if ($this->prices_include_tax) :
|
||||
return number_format( ($item['cost'] * (1 + ($item['taxrate']/100)) - ( $item['row_discount'] / $item['qty'] )) , 2, '.', '');
|
||||
else :
|
||||
return number_format( ($item['cost'] - ( $item['row_discount'] / $item['qty'] )) * (1 + ($item['taxrate']/100)) , 2, '.', '');
|
||||
endif;
|
||||
|
||||
return number_format( $item['cost'] * (1 + ($item['taxrate']/100)) , 2, '.', '');
|
||||
else :
|
||||
|
||||
return number_format( $item['cost'] - ( $item['row_discount'] / $item['qty'] ) );
|
||||
|
||||
return number_format( $item['cost'] , 2, '.', '');
|
||||
endif;
|
||||
}
|
||||
|
||||
/** Calculate row cost - useful for gateways */
|
||||
function get_row_cost( $item, $inc_tax = false ) {
|
||||
|
||||
if ($inc_tax) :
|
||||
|
||||
if ($this->prices_include_tax) :
|
||||
return number_format( ( ($item['cost'] * $item['qty']) * (1 + ($item['taxrate']/100)) - $item['row_discount'] ) , 2, '.', '');
|
||||
else :
|
||||
return number_format( (($item['cost'] * $item['qty']) - $item['row_discount']) * (1 + ($item['taxrate']/100)) , 2, '.', '');
|
||||
endif;
|
||||
|
||||
return number_format( ($item['cost'] * $item['qty']) * (1 + ($item['taxrate']/100)) , 2, '.', '');
|
||||
else :
|
||||
|
||||
return number_format( (($item['cost'] * $item['qty']) - $item['row_discount']) );
|
||||
|
||||
return number_format( $item['cost'] * $item['qty'] , 2, '.', '');
|
||||
endif;
|
||||
}
|
||||
|
||||
|
@ -244,7 +226,9 @@ class woocommerce_order {
|
|||
|
||||
foreach ($this->items as $item) :
|
||||
|
||||
$subtotal += round(($item['cost']*$item['qty']) * (($item['taxrate']/100) + 1), 2);
|
||||
if (!isset($item['base_cost'])) $item['base_cost'] = $item['cost'];
|
||||
|
||||
$subtotal += round(($item['base_cost']*$item['qty']) * (($item['taxrate']/100) + 1), 2);
|
||||
|
||||
endforeach;
|
||||
|
||||
|
@ -383,16 +367,14 @@ class woocommerce_order {
|
|||
<td style="text-align:left;">'.$item['qty'].'</td>
|
||||
<td style="text-align:left;">';
|
||||
|
||||
if ($this->display_cart_ex_tax || !$this->prices_include_tax) :
|
||||
|
||||
if ($this->prices_include_tax) $ex_tax_label = 1; else $ex_tax_label = 0;
|
||||
$return .= woocommerce_price( $item['cost']*$item['qty'], array('ex_tax_label' => $ex_tax_label ));
|
||||
|
||||
else :
|
||||
|
||||
$return .= woocommerce_price( round(($item['cost']*$item['qty']) * (($item['taxrate']/100) + 1), 2) );
|
||||
|
||||
endif;
|
||||
if (!isset($item['base_cost'])) $item['base_cost'] = $item['cost'];
|
||||
|
||||
if ($this->display_cart_ex_tax || !$this->prices_include_tax) :
|
||||
if ($this->prices_include_tax) $ex_tax_label = 1; else $ex_tax_label = 0;
|
||||
$return .= woocommerce_price( $item['base_cost']*$item['qty'], array('ex_tax_label' => $ex_tax_label ));
|
||||
else :
|
||||
$return .= woocommerce_price( round(($item['base_cost']*$item['qty']) * (($item['taxrate']/100) + 1), 2) );
|
||||
endif;
|
||||
|
||||
$return .= '
|
||||
</td>
|
||||
|
|
|
@ -280,8 +280,8 @@ function woocommerce_add_order_item() {
|
|||
</td>
|
||||
<?php do_action('woocommerce_admin_order_item_values', $_product); ?>
|
||||
<td class="quantity"><input type="text" name="item_quantity[<?php echo $index; ?>]" placeholder="<?php _e('0', 'woothemes'); ?>" value="1" /></td>
|
||||
<td class="cost"><input type="text" name="base_item_cost[<?php echo $index; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" value="<?php echo esc_attr( $_product->get_price_excluding_tax( false ) ); ?>" /></td>
|
||||
<td class="cost"><input type="text" name="item_cost[<?php echo $index; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" value="<?php echo esc_attr( $_product->get_price_excluding_tax( false ) ); ?>" /></td>
|
||||
<td class="discount"><input type="text" name="item_discount[<?php echo $index; ?>]" placeholder="<?php _e('0.00', 'woothemes'); ?>" /></td>
|
||||
<td class="tax"><input type="text" name="item_tax_rate[<?php echo $index; ?>]" placeholder="<?php _e('0.0000', 'woothemes'); ?>" value="<?php echo esc_attr( $_product->get_tax_base_rate() ); ?>" /></td>
|
||||
<td class="center">
|
||||
<input type="hidden" name="item_id[<?php echo $index; ?>]" value="<?php echo esc_attr( $_product->id ); ?>" />
|
||||
|
|
|
@ -1323,16 +1323,14 @@ function woocommerce_order_details_table( $order_id ) {
|
|||
echo ' </td>
|
||||
<td>'.$item['qty'].'</td>
|
||||
<td>';
|
||||
|
||||
if (!isset($item['base_cost'])) $item['base_cost'] = $item['cost'];
|
||||
|
||||
if ($order->display_cart_ex_tax || !$order->prices_include_tax) :
|
||||
|
||||
if ($order->display_cart_ex_tax || !$order->prices_include_tax) :
|
||||
if ($order->prices_include_tax) $ex_tax_label = 1; else $ex_tax_label = 0;
|
||||
echo woocommerce_price( $item['cost']*$item['qty'], array('ex_tax_label' => $ex_tax_label ));
|
||||
|
||||
echo woocommerce_price( $item['base_cost']*$item['qty'], array('ex_tax_label' => $ex_tax_label ));
|
||||
else :
|
||||
|
||||
echo woocommerce_price( round(($item['cost']*$item['qty']) * (($item['taxrate']/100) + 1), 2) );
|
||||
|
||||
echo woocommerce_price( round(($item['base_cost']*$item['qty']) * (($item['taxrate']/100) + 1), 2) );
|
||||
endif;
|
||||
|
||||
echo '</td>
|
||||
|
|
Loading…
Reference in New Issue