Hide free shipping when subtotal is greater than 0 in WooCommerce - php

I'm using Free Product Sample for the WooCommerce plugin and trying to set conditional free shipping only for a Sample product, sample product cost is 0 and therefore I'm trying to hide free shipping unless the order subtotal amount is 0.
To put it in a nutshell:
I want to offer free shipping only for sample products and, the free shipping method should only visible for a product having subtotal = 0
Screenshot for further clarification:
My attempted code:
function ts_hide_shipping_for_order_total( $rates ) {
$rate = array();
$order_total = WC()->cart->get_subtotal();
if( $order_total > 0 ) {
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping:20' === $rate->get_method_id() ) {
$rate[ $rate_id ] = $rate;
}
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'ts_hide_shipping_for_order_total', 100 );
OR
add_filter( 'woocommerce_package_rates', 'hide_shipping_except_local_when_free_is_available', 100 );
function hide_shipping_except_local_when_free_is_available($rates) {
$free = $local = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping:20' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
}
}
return ! empty( $free ) ? array_merge( $free, $local ) : $rates;
}
But both codes do not give me the desired result. Can anyone point me in the right direction?

To hide/unset the "free shipping", as long as the subtotal is greater than 0, you can use the following.
So you get:
function filter_woocommerce_package_rates( $rates, $package ) {
// Get subtotal
$subtotal = $package['cart_subtotal'];
// Hide free shipping if subtotal > 0
if ( $subtotal > 0 ) {
// Loop trough
foreach ( $rates as $rate_id => $rate ) {
if ( $rate->method_id === 'free_shipping' ) {
unset( $rates[$rate_id] );
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
Additional question: Hide the other methods when subtotal <= 0
function filter_woocommerce_package_rates( $rates, $package ) {
// Get subtotal
$subtotal = $package['cart_subtotal'];
// Loop trough
foreach ( $rates as $rate_id => $rate ) {
if ( $rate->method_id === 'free_shipping' ) {
// Hide free shipping if subtotal > 0
if ( $subtotal > 0 ) {
unset( $rates[$rate_id] );
}
} else {
// Hide other methods when subtotal <= 0
if ( $subtotal <= 0 ) {
unset( $rates[$rate_id] );
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );

Related

PHP How to disable shipping methods based on subtotal

I try to disable some shipping methods based on cart subtotal (after discounts).
// Disable Woocommerce shipping methods based on cart subtot
function wpsh_hide_shipping_based_on_subtotal( $rates, $package ) {
// Retrieve cart subtotal
//$cart_subtotal = $package['contents_cost'];
$cart_subtotal = WC()->cart->get_cart_contents_total();
// Shipping rate to be excluded
$shipping_id1 = 'flat_rate:73';
$shipping_id2 = 'flat_rate:75';
$shipping_id3 = 'local_pickup:69';
$shipping_id4 = 'flat_rate:76';
$shipping_id5 = 'local_pickup:79';
if ( $cart_subtotal < 99 ){
unset( $rates[ $shipping_id4 ] );
unset( $rates[ $shipping_id5 ] );
}
if ( $cart_subtotal >= 99 ){
unset( $rates[ $shipping_id1 ] );
unset( $rates[ $shipping_id2 ] );
unset( $rates[ $shipping_id3 ] );
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'wpsh_hide_shipping_based_on_subtotal', 10, 2 );
This seems to work, but sometimes, especially with variable products it doesnt hide shipping methods below 99 subtotal. I dont have any clues why. Can you help me?
Try with woocommerce_shipping_packages to hide the shipping method.
add_filter( 'woocommerce_shipping_packages', array( $this, 'hide_shipping_rates_from_packages'), 10, 1 );
public function hide_shipping_rates_from_packages( $packags ) {
if ( !empty( WC()->cart ) ) {
$cart_subtotal = wc_format_decimal( WC()->cart->get_cart_subtotal( false ) ); // Without include compound taxes.
if ( $cart_subtotal < 80 ) {
foreach( $packags as $index => $package ) {
unset($packags[$index]['rates']['free_shipping:1']);
}
}
}
return $packags;
}
For recurring carts, use the woocommerce_package_rates filter to hide shipping methods. This filter affects the session-stored package details and this filter is not triggered when rates are stored in the WC session data for this package.
add_filter( 'woocommerce_package_rates', array( $this, 'hide_shipping_rates_from_package_rates'), 10, 2 );
public function hide_shipping_rates_from_package_rates( $package_rates, $package ) {
if ( !empty( WC()->cart ) ) {
$cart_subtotal = wc_format_decimal( WC()->cart->get_cart_subtotal( false ) ); // Without include compound taxes.
if ( $cart_subtotal < 80 ) {
unset($packag_rates['free_shipping:1']);
}
}
return $packag_rates;
}

Hide multiple shipping methods for specific products in Woocommerce [duplicate]

I want to hide a set of shipping methods if a set of products are selected on WooCommerce
I think I'm almost there but I am getting an error on the unset( $rates[$method_ids] ) line.
Here's what I've got so far:
add_filter( 'woocommerce_package_rates', 'specific_products_shipping_methods_hide_many', 10, 2 );
function specific_products_shipping_methods_hide_many( $rates, $package ) {
$product_ids = array( 240555 ); // HERE set the product IDs in the array
$method_ids = array( 'flat_rate:7', 'flat_rate:13', 'flat_rate:26', 'flat_rate:27', 'local_pickup:24' ) ; // HERE set the shipping method IDs
$found = false;
// Loop through cart items Checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
if ( in_array( $cart_item['product_id'], $product_ids ) ){
$found = true;
break;
}
}
if ( $found )
unset( $rates[$method_ids] );
return $rates;
}
Any advice?
You are close, but you need to loop through $rates and if it occurs $rate_id, you can unset it
So you get:
function filter_woocommerce_package_rates( $rates, $package ) {
// Set the product IDs in the array
$product_ids = array( 240555, 30 );
// Set the rate IDs in the array
$rate_ids = array( 'flat_rate:7', 'flat_rate:13', 'flat_rate:26', 'flat_rate:27', 'local_pickup:24', 'local_pickup:1', 'free_shipping:2' );
// Initialize
$found = false;
// Loop through cart items checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
// Checks if a value exists in an array
if ( in_array( $cart_item['product_id'], $product_ids ) ) {
$found = true;
break;
}
}
// True
if ( $found ) {
// Loop trough
foreach ( $rates as $rate_id => $rate ) {
// Checks if a value exists in an array
if ( in_array( $rate_id, $rate_ids ) ) {
unset( $rates[$rate_id] );
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );

Tax based on cart subtotal

I'm trying with the code below to set to zero rate the tax when selling to a European Union state an order of value above 150 euro but I can't get it to work. Any idea what I'm doing wrong?
add_filter( 'woocommerce_product_get_tax_class', 'eu_tax_rate_based_on_subtotal', 1, 2 );
function eu_tax_rate_based_on_subtotal( $tax_class, $product ) {
$EU_countries = array('AT','BE','BG','CY','CZ','DE','DK','EE','ES','FI','FR','GR','HR','HU','IE','IT','LT','LU','LV','MT','NL','PL','PT','RO','SE','SI','SK');
if ( in_array( WC()->customer->get_shipping_country(), $EU_countries ) ){
if ( WC()->cart->subtotal >= 150 )
$tax_class = 'zero';
}
return $tax_class;
}
Use this filter if you want to remove taxes without a dynamic requirements.
function sto_calc_tax($taxes, $price, $rates, $price_includes_tax, $deprecated){
if (WC()->cart->subtotal >= 150 && in_array( WC()->customer->get_shipping_country(), array('AT','BE','BG','CY','CZ','DE','DK','EE','ES','FI','FR','GR','HR','HU','IE','IT','LT','LU','LV','MT','NL','PL','PT','RO','SE','SI','SK') ) ){
foreach ($taxes as $index => $tax) {
$taxes[$index] = 0;
}
}
return $taxes;
}
add_filter('woocommerce_calc_tax', 'sto_calc_tax', 10, 5);

Custom Coupon type woocommerce wordpress

I need to create custom coupon type. Because i had custom calculation for custom coupon. Anyone out there help me.
Coupon calculation:
the cart has one product and value is 5000, then custom coupon code applied. The cart total need to change 2000. Similarly the cart has 2 product and value is 7000. If the custom coupon code applied, then cart total need to be 4000.
So the coupon need to make the cart total as flat 2000 for one product
In newer versions of WooCommerce, you will need to
Register a custom coupon type
Validate the coupon
Calculate & Apply the discount
Register custom coupon type
add_filter( 'woocommerce_coupon_discount_types', 'custom_coupon_type',10, 1);
function custom_coupon_type( $discount_types ) {
$discount_types['my_type'] =__( 'My New Coupon Type', 'woocommerce' );
return $discount_types;
}
Validate the coupon
add_filter('woocommerce_coupon_is_valid_for_product', 'validate_custom_coupon', 10, 4);
function validate_custom_coupon($valid, $product, $coupon, $values){
if ( ! $coupon->is_type( array( 'my_type' ) ) ) {
return $valid;
}
$product_cats = wp_get_post_terms( $product->id, 'product_cat', array( "fields" => "ids" ) );
// SPECIFIC PRODUCTS ARE DISCOUNTED
if ( sizeof( $coupon->product_ids ) > 0 ) {
if ( in_array( $product->id, $coupon->product_ids ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $coupon->product_ids ) ) || in_array( $product->get_parent(), $coupon->product_ids ) ) {
$valid = true;
}
}
// CATEGORY DISCOUNTS
if ( sizeof( $coupon->product_categories ) > 0 ) {
if ( sizeof( array_intersect( $product_cats, $coupon->product_categories ) ) > 0 ) {
$valid = true;
}
}
// IF ALL ITEMS ARE DISCOUNTED
if ( ! sizeof( $coupon->product_ids ) && ! sizeof( $coupon->product_categories ) ) {
$valid = true;
}
// SPECIFIC PRODUCT IDs EXLCUDED FROM DISCOUNT
if ( sizeof( $coupon->exclude_product_ids ) > 0 ) {
if ( in_array( $product->id, $coupon->exclude_product_ids ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $coupon->exclude_product_ids ) ) || in_array( $product->get_parent(), $coupon->exclude_product_ids ) ) {
$valid = false;
}
}
// SPECIFIC CATEGORIES EXLCUDED FROM THE DISCOUNT
if ( sizeof( $coupon->exclude_product_categories ) > 0 ) {
if ( sizeof( array_intersect( $product_cats, $coupon->exclude_product_categories ) ) > 0 ) {
$valid = false;
}
}
// SALE ITEMS EXCLUDED FROM DISCOUNT
if ( $coupon->exclude_sale_items == 'yes' ) {
$product_ids_on_sale = wc_get_product_ids_on_sale();
if ( isset( $product->variation_id ) ) {
if ( in_array( $product->variation_id, $product_ids_on_sale, true ) ) {
$valid = false;
}
} elseif ( in_array( $product->id, $product_ids_on_sale, true ) ) {
$valid = false;
}
}
return $valid;
}
Calculate & Apply Discount
add_filter('woocommerce_coupon_get_discount_amount', 'wc_cpn_disc', 10, 5);
function wc_cpn_disc($discount, $discounting_amount, $cart_item, $single, $coupon) {
// IF TYPE MATCHES PERFORM CUSTOM CALCULATION
if ($coupon->type == 'my_type')
$discount = $cart_item['quantity'] * 2000;
return $discount;
}
Sources:
#raju_odi's answer on this exact question
#Chris Morris's answer to Woocommerce custom coupon type with custom discount always return 0
Please use below code in your active theme's function.php
function custom_discount_type( $discount_types ) {
$discount_types['custom_discount'] =__( 'custom discount', 'woocommerce' );
return $discount_types;
}
// add the hooks
add_filter( 'woocommerce_coupon_discount_types', 'custom_discount_type',10, 1);
//function to get coupon amount for "custom_discount"
function woocommerce_coupon_get_discount_amount($discount, $discounting_amount, $cart_item, $single, $coupon) {
if ($coupon->code == 'custom'){
//echo "yes custom discount"; //if $coupon->type == 'fixed_cart' or 'percent' or 'fixed_product' or 'percent_product' The code Works
$discount = $cart_item['quantity'] * 2000;
return $discount;
} else {
return $discount;
}
}
//add hook to coupon amount hook
add_filter('woocommerce_coupon_get_discount_amount', 'woocommerce_coupon_get_discount_amount', 10, 5);
Note : Please add your added coupon name here on this line if ($coupon->code == 'your_added_coupon_here')
Working fine and tested.

Woocommerce - filter shipping rates by date

I am trying to hide specific shopping rates during the weekdays and offer them only on weekend (friday evening to be exact). I have 5 rates, I would like to show first 3 (by id ) always and rate 4 and 5 only on friday afternoon and night.
add_filter( 'woocommerce_package_rates', 'hide_friday_special_shipping_method', 10, 2 );
function hide_friday_special_shipping_method ( $rates, $package ) {
if ( date("N")==5 && date("G")>=15 || date("N")==6 && date("G")<=8) {
foreach ( $rates as $rate_id => $rate ) {
if ( '5' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
= array();
}
foreach ( $rates as $rate_id => $rate ) {
if ( '4' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
= array();
}
return $rates;
}
It doesnt return anything. Could you please advice me on what should i do ?
function hide_friday_special_shipping_method ( $rates ) {
if ( date("N")==4 && date("G")>=1 || date("N")==6 && date("G")<=8) {
$rates = unset($rates[3]);
$rates = unset($rates[4]);
}
return $rates;
}
print_r($rates);
Tried this but it doesnt work either..

Categories