Tax exclusive if coupon applied else tax inclusive in items - php

I have setup taxes inclusive for all my items and filled MRP in price. But now I want to apply tax inclusive if customer didn't applied coupon i.e. buying on MRP. But when customer applies coupon I need to apply taxes on after discount amount.
Is it possible with settings within Woocommerce or is there any plugin available?
For e.g.
**Case I**
Product MRP = 670
Shipping = 50
Tax 18% = 102
Final price = 670 (Including Taxes)
It's Fine.
**Case II**
Product MRP = 670
Discount 40%= 268
Price = 402
Shipping = 50
Tax 18% = 61
Final price = 452 (Including Taxes)
But I need tax to calculated exclusively on discounted price i.e. 402+18% = 474+50 (Ship) = 524
I have tried following filter in my custom plugin:
add_filter( 'woocommerce_calc_tax', 'inc_or_exc',10,3 );
// add_filter( 'woocommerce_calculate_totals', 'calculate_totals',11 );
function inc_or_exc( $taxes,$price,$rates ) {
// echo "<pre>";
if(!empty(WC()->cart->coupon_discount_amounts)){
return WC_Tax::calc_exclusive_tax( $price, $rates );
}else{
return WC_Tax::calc_inclusive_tax( $price, $rates );
}
}
But it calculates taxes bit strange. If item MRP is 100, it shows 98.85 and also totals are not updating with new taxes and shipping rates after plugin run. If I disable plugin then item MRP is shown fine i.e. 100.

Finally I have solved it.
First I applied inclusive exlusive filter. Then called woocommerce_calculated_total with custom condition and achieved my motive.
add_filter( 'woocommerce_calc_tax', 'inc_or_exc',10,3 );
// do_action('add_points');
add_filter( 'woocommerce_calculated_total', 'custom_calculated_total', 10, 2 );
function inc_or_exc( $taxes,$price,$rates ) {
// echo "<pre>";
if(!empty(WC()->cart->coupon_discount_amounts)){
return WC_Tax::calc_exclusive_tax( $price, $rates );
}else{
return WC_Tax::calc_inclusive_tax( $price, $rates );
}
}
function custom_calculated_total( $total, $cart ){
// echo "<pre>";
if(!empty(WC()->cart->coupon_discount_amounts)){
return round( $total + WC()->cart->get_cart_contents_tax(), $cart->dp );
}else{
return round( $total, $cart->dp );
}
}

Related

Modify product price based on price with tax included

I'm building a Woocommerce store and I need to get all the prices with tax included to end in zero (For example, if the original price with tax included is 1234, then I round it to 1240).
Products are imported to my website in bulk (+2800 products) but they have the price without tax. I configured the tax in woocommerce settings and I display prices with tax included in the store.
To fix the "ending in 0" problem, I created a method to change the tax value so the final price ends in 0:
// Calculate tax
function filter_woocommerce_calc_tax( $taxes, $price, $rates, $price_includes_tax, $suppress_rounding ) {
$key = array_search('IVA', array_column_keys($rates, 'label')); // find tax with label "IVA"
$tax = $taxes[$key]; // get the current tax
$subtotal = $price + $tax; // get the total
$final = ceil($subtotal / 10) * 10; // modify the total so it ends in 0
$new_tax = $final - $price; // calculate new tax price
$taxes[$key] = $new_tax; // update tax in array
return $taxes; // return new calculated taxes
};
add_filter( 'woocommerce_calc_tax', 'filter_woocommerce_calc_tax', 10, 5 );
It works really good, but I figured that if I change the tax price, I'm actually changing the tax rate (%) and I can't do that for legal reasons.
That's why I wanted to change the price of the product without tax instead.
I can use the same method:
$final = ceil($subtotal / 10) * 10; // modify the total so it ends in 0
$new_price = $final - $tax; // new price without tax
But I don't know what hook to use to achieve this.
Is is possible to change the price with hooks and filters?
I finally got a solution, first I created a method to calculate the prices without tax:
function get_net_sales_price($price, $tax_rate = 0) {
$subtotal = $price + (1+$tax_rate);
$final = ceil($subtotal / 10) * 10;
$new_price = $final / (1+$tax_rate);
return $new_price;
}
Then I got the taxes based on the product and customer location (thanks to this answer):
function get_tax_rates($product) {
// Get an instance of the WC_Tax object
$tax_obj = new WC_Tax();
// Get the tax data from customer location and product tax class
return $tax_obj->find_rates(array(
'country' => WC()->customer->get_shipping_country() ? WC()->customer->get_shipping_country() : WC()->customer->get_billing_country(),
'state' => WC()->customer->get_shipping_state() ? WC()->customer->get_shipping_state() : WC()->customer->get_billing_state(),
'city' => WC()->customer->get_shipping_city() ? WC()->customer->get_shipping_city() : WC()->customer->get_billing_city(),
'postcode' => WC()->customer->get_shipping_city() ? WC()->customer->get_shipping_city() : WC()->customer->get_billing_city(),
'tax_class' => $product->get_tax_class()
));
}
And finally I use a hook to return the correct price for the product (woocommerce then adds the tax when needed):
function filter_woocommerce_price($price, $product) {
$rates = get_tax_rates($product);
// Finally we get the tax rate and calculare net sales price:
if( ! empty($rates) ) {
$key = array_search('IVA', array_column_keys($rates, 'label'));
return get_net_sales_price($price, $rates[$key]['rate'] / 100);
} else {
return get_net_sales_price($price);
}
}
add_filter('woocommerce_product_get_price', 'filter_woocommerce_price', 99, 2 );
add_filter('woocommerce_product_get_regular_price', 'filter_woocommerce_price', 99, 2 );
add_filter('woocommerce_product_variation_get_regular_price', 'filter_woocommerce_price', 99, 2 );
add_filter('woocommerce_product_variation_get_price', 'filter_woocommerce_price', 99, 2 );
Now I'm getting the right tax amount, and also all the product prices end in 0.

If coupon amount is higher than cart subtotal, also reduce the amount of shipping totals

The code is supposed to check if the fixed coupon amount is bigger than cart subtotals. If yes, subtract the remainder of the price from shipping totals. It's in my functions file.
add_filter('woocommerce_package_rates', 'custom_shipping_costs', 10, 2 );
function custom_shipping_costs( $rates, $package ){
//get the shipping total, cart subtotal and coupon amount
$dostava = $cart->shipping_total;
$iznos = $woocommerce->cart->get_cart_subtotal();
$kuponi = $woocommerce->cart->discount_total;
//subtract the coupon amount from cart subtotal
$razlika = $iznos - $kuponi;
//now check if it's higher than what's in the cart, if yes, set the new shipping costs
if($razlika < 0){
$novadostava = $dostava - $razlika;
$cart->shipping_total = $novadostava;
}
return $rates;
}
Unfortunately.. it doesn't work. Any suggestions?
Here is an example since there are more to consider to it as taxes rates shipping methods if must define etc but current example works as it
We have product that cost 18$ and coupon that discount 20$ with shipping tax 15$ at the end we get 13$ total - https://prnt.sc/365xV2BWx2wA
add_filter('woocommerce_package_rates', 'custom_shipping_costs');
function custom_shipping_costs( $rates ){
$cart = WC()->cart;
if($rates):
foreach($rates as $rate_key => $rate):
$dostava = $rate->get_cost();
endforeach;
endif;
$iznos = $cart->subtotal;
$kuponi = $cart->get_coupons();
if($kuponi):
foreach($kuponi as $kupon):
$kuponi_amount = $kupon->get_amount();
endforeach;
endif;
$razlika = $iznos - $kuponi_amount;
$razlika = abs($razlika);
if($razlika > 0){
$novadostava = $dostava - $razlika;
$rates[$rate_key]->cost = $novadostava;
}
return $rates;
}

WooCommerce doesn't show actual price on cart page without tax

I have build webstore on WooCommerce. I have added standard tax rate when the customer fills their billing address and select country tax will be applied on the checkout page that is working fine I want to show actual price of products on cart page without multiply my tax ratio with my product price
This is checkout page show tax when a country is selected
this is cart page showing tax calculated value and grand total show without tax value
I have added this function in my function.php file but no success
function wc_remove_cart_tax_totals( $tax_totals, $instance ) {
if( is_cart() ) {
$tax_totals = array();
}
return $tax_totals;
}
add_filter( 'woocommerce_cart_tax_totals', 'wc_remove_cart_tax_totals', 10, 2 );
// Show the cart total excluding tax.
function wc_exclude_tax_cart_total( $total, $instance ) {
// If it is the cart subtract the tax
if( is_cart() ) {
$total = round( WC()->cart->cart_contents_total + WC()->cart->shipping_total + WC()->cart->fee_total, WC()->cart->dp );
}
return $total;
}
add_filter( 'woocommerce_calculated_total', 'wc_exclude_tax_cart_total', 10, 2 );
add_filter( 'woocommerce_subscriptions_calculated_total', 'wc_exclude_tax_cart_total', 10, 2 );

WooCommerce - Display Fees per product not per Cart

I have to add a charge per shopping cart line in a WooCommerce shop. This fee is intended to change the unit price and the line sum.
This fee is not intended as a fee for shipping and grand total.
There is a service fee ($54) per basket line / per product.
For example, $ 0.81 per product plus a service-fee of $ 54 will result in $ 1.81 per product and a total of $ 94.66 at 50 pieces.
What I have so far ...
// Change the line total price
add_filter( 'woocommerce_get_discounted_price', 'calculate_discounted_price', 10, 2 );
// Display the line total price
add_filter( 'woocommerce_cart_item_subtotal', 'display_discounted_price', 10, 2 );
function calculate_discounted_price( $price, $values ) {
$price += 5;
return $price;
}
function display_discounted_price( $values, $item ) {
return wc_price( $item[ 'line_total' ] );
}
Many thanks for your help!

Customize Tax amount in "woocommerce_package_rates" hook

I recently tried to modify all my shipping rates with hook to apply discount.
Here's my code :
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates' );
function woocommerce_package_rates( $rates ) {
$user_id = get_current_user_id();
if ( ! wc_memberships_is_user_active_member( $user_id, 'silver' ) ) { return $rates; }
$discount_amount = 30; // 30%
foreach($rates as $key => $rate ) {
$rates[$key]->cost = $rates[$key]->cost - ( $rates[$key]->cost * ( $discount_amount/100 ) );
}
return $rates;
}
But one more step is the tax ! I got wrong tax.
For example I have my shipping rate who cost 3$. With the discount, it's now 2,10$.
I buy one item for 2$ and the shipping 2.10$.
I got 1$ for the tax (as the 3$ shipping cost. look like he doesn't take the changes) and normally it's 0.82$.
What do I need to get the correct tax calculation?
Update: related to tax cost calculation for the shipping methods
There is some little errors on your code and you have missed the tax calculation discount. I have revisited your code a bit, you should try this:
add_filter( 'woocommerce_package_rates', 'conditional_shipping_discount', 10, 2 );
function conditional_shipping_discount( $rates, $packages ) {
$user_id = get_current_user_id();
if ( ! wc_memberships_is_user_active_member( $user_id, 'silver' ) ) return $rates;
$percent = 30; // 30%
$discount = 1 - ($percent / 100);
foreach($rates as $rate_key => $rate_values ) {
// Get original cost
$original_cost = $rates[$rate_id]->cost;
// Calculate the discounted rate cost
$new_cost = $original_cost * $discount;
// Set the discounted rate cost
$rates[$rate_key]->cost = number_format(new_cost, 2);
// calculate the conversion rate (for taxes)
$conversion_rate = $new_cost / $original_cost;
// Taxes rate cost (if enabled)
$taxes = array();
foreach ($rate->taxes as $key => $tax){
if( $tax > 0 ){ // set the new tax cost
// set the new line tax cost in the taxes array
$taxes[$key] = number_format( $tax * $conversion_rate, 2 );
}
}
// Set the new taxes costs
$rates[$rate_key]->taxes = $taxes
}
return $rates;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
You should need to refresh the shipping caches:
First this code is already saved on your function.php file.
In Shipping settings, enter in a Shipping Zone and disable a Shipping Method and "save". Then re-enable that Shipping Method and "save". You are done.
Below code #LoicTheAztec without mistakes:
add_filter( 'woocommerce_package_rates', 'conditional_shipping_discount', 10, 2 );
function conditional_shipping_discount( $rates, $packages ) {
$user_id = get_current_user_id();
if ( ! wc_memberships_is_user_active_member( $user_id, 'silver' ) ) return $rates;
$percent = 30; // 30%
$discount = 1 - ($percent / 100);
foreach($rates as $rate_key => $rate_values ) {
// Get original cost
$original_cost = $rates[$rate_key]->cost;
// Calculate the discounted rate cost
$new_cost = $original_cost * $discount;
// Set the discounted rate cost
$rates[$rate_key]->cost = number_format($new_cost, 2);
// calculate the conversion rate (for taxes)
$conversion_rate = $new_cost / $original_cost;
// Taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $tax > 0 ){ // set the new tax cost
// set the new line tax cost in the taxes array
$taxes[$key] = number_format( $tax * $conversion_rate, 2 );
}
}
// Set the new taxes costs
$rates[$rate_key]->taxes = $taxes;
}
return $rates;
}
The problem with the answers above is that you're calculating the tax based on the calculations already made for the original cost. What if, for example, a plugin is calculating the tax based on the shipping cost? For example, 10% if $100 or above, 20% if $200 or above, 0% if less than $100.
If the original cost was $150 and you're applying a $60 discount, the discounted cost would be $90 and no tax would apply in the aforementioned scenario. So we need a way to modify the cost before the tax is calculated. This way we don't have to recalculate the tax ourselves and we reduce bugs like the example in the first paragraph.
For one of my plugins I'm using the woocommerce_shipping_method_add_rate_args filter, which is called by \WC_Shipping_Method::add_rate(). This method is called everytime a \WC_Shipping_Method instance adds a rate.
This filter will accept an array as its first argument, which is the rate data. This array has a 'cost' entry which is what we want to modify. Keep in mind that this can be a scalar (apparently, a numeric string) or an array. Just check if it's an array when dealing with this:
add_filter('woocommerce_shipping_method_add_rate_args', function(array $rateArguments) : array {
// Total up the cost. Taken from the WooCommerce source code. woocommerce/includes/abstracts/abstract-wc-shipping-method.php
$totalCost = is_array( $rateArguments['cost'] ) ? array_sum( $rateArguments['cost'] ) : $rateArguments['cost'];
$rateArguments['cost'] = 'here the final cost';
return $rateArguments;
});

Categories