woocommerce tiered flat rate based on a custom field - woocommerce

I have a website where customer chooses a zone in a dropdown in billing fields. These are 4 zones: zone1, zone2 and zone3 as an example.
The idea is that if customer chose zone1 and total cart is less than $1000, customer needs to pay a shipping rate of $100. If more than $1000, customer gets free shipping.
I need to replicate that for the other 2 zones with different cart amounts and shipping rates. Is this possible?
Right now, I have the following working code but customer has to manually choose a flat rate. Problem is, of course, customers... If free shipping is displayed, they will choose that one knowing they dont apply for that option when total amount is less for their zone.
/* Change shipping based on total cost purchased. */
add_filter( 'woocommerce_package_rates', 'bbloomer_woocommerce_tiered_shipping', 10, 2 );
function bbloomer_woocommerce_tiered_shipping( $rates, $package ) {
$threshold_centro = 1000;
$threshold_hasta_el_5 = 1500;
$threshold_arelauquen = 2000;
if ( WC()->cart-> cart_contents_total < $threshold_centro ) {
unset( $rates['free_shipping:9'] );
}
elseif ( WC()->cart-> cart_contents_total < $threshold_hasta_el_5 ) {
unset( $rates['flat_rate:2'] );
}
elseif ( WC()->cart-> cart_contents_total < $threshold_arelauquen ) {
unset( $rates['flat_rate:2'], $rates['flat_rate:3'] );
}
else {
unset( $rates['flat_rate:2'], $rates['flat_rate:3'], $rates['flat_rate:4'], $rates['flat_rate:5'], $rates['flat_rate:6'] );
}
return $rates;
}
and the custom field is this one: billing_wcccf_id_qXZZegrC774HULq

Try to set a WC session when you trigger the selectbox and the use it in your if statement to get the right shipping rate or use a switch
WC->session->set('your session name', 'value')
WC->session->get('your session')

Related

Hide express paid shipping options when stock of the product is 0 or less than 0 (backorder cases) in Wocommerce checkout

I set 2 methods of delivery:
Express shipping 48 hours at a cost which es a % of the total cart $ amount
Normal Free shipping in 29 days
The functionality that I want is the following:
If the stock of the product is = 0 or less than 0 (backorder is allowed), the Express shipping option should be hidden. Just must show the Normal free shipping option.
If the stock of the product is >0, both options should be shown.
If I selected more than one product, and one or more of the products does not have stock, the Express shipping option also should be hidden.
From another answer related to this question, I tried the script showed in the answer.
The problem is the following: in the last part of the script there is a mention to a variable in an external plugin.
How I adapt the code to a more generic woocommerce without that plugin?
Script:
/* !Hide Shipping Options Woocommerce */
add_filter( 'woocommerce_available_shipping_methods', 'hide_shipping_based_on_quantity' , 10, 1 );
function check_cart_for_oos() {
// load the contents of the cart into an array.
global $woocommerce;
$found = false;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$_product_quantity = $_product->get_stock_quantity();
$_cart_quantity = $values['quantity'];
if (($_product_quantity <= 0) || ($_cart_quantity > $_product_quantity)) {
$found = true;
break;
}
}
return $found;
}
function hide_shipping_based_on_quantity( $available_methods ) {
// use the function check_cart_for_oos() to check the cart for products with 0 stock.
if ( check_cart_for_oos() ) {
// remove the rate you want
unset( $available_methods['table_rate_shipping_next-day'] ); // Replace "table_rate_shipping_next-day" with "table_rate_shipping_your-identifier".
}
// return the available methods without the one you unset.
return $available_methods;
}
From: Remove next day shipping method for out of stock items in Woocommerce
In that answer, it's already mentioned to use your own shipping method identifier. So you just need to replace the shipping method identifier with yours.
// use the function check_cart_for_oos() to check the cart for products with 0 stock.
if ( check_cart_for_oos() ) {
// remove the rate you want
unset( $available_methods['USE_YOUR_OWN_IDENTIFIER_HERE'] ); // Replace "table_rate_shipping_next-day" with "table_rate_shipping_your-identifier".
}

WooCommerce Distance Rate Shipping causing tax rate to reset

I am on the verge of losing it with this problem. So what I am attempting is to apply Zero rate tax rate when a specific coupon ('12345') is applied to the order. This site also has the plugin WooCommerce Distance Rate Shipping installed which adds its own costs and tax to the order based on billing distance.
While the billing address fields are empty, the following code successfully detects the coupon in question and sets tax rate to 'Zero Rate':
function apply_matched_coupons() {
$coupon_code = '12345';
if ( !is_admin() && WC()->cart->has_discount( $coupon_code ) ) {
$tax_class = 'Zero rate';
}
return $tax_class;
};
add_action( 'woocommerce_product_tax_class','apply_matched_coupons' );
But when an address is typed in the billing fields, the Woocommerce order update AJAX works and the WooCommerce Distance Rate Shipping plugin reads the billing addresss, re-checks its rules, applies its costs and also adds its tax. Hence, overwriting my Zero Tax rate set earlier. Screenshot is attached. I believe a hook like woocommerce_checkout_update_order_review may work which fires each time the order is updated on checkout, but can't figure out exactly how to set it.
The plugin's page here does show an example to set the $rule_cost to 0 with this code:
add_filter( 'woocommerce_distance_rate_shipping_rule_cost_distance_shipping', function( $rule_cost, $rule, $distance, $package ) {
$order_total = $package['contents_cost'];
if ( $order_total > 100 && $distance <= 5 ) {
$rule_cost = 0;
}
return $rule_cost;
}, 10, 4 );
Could this help in any way?
screenshot of extra tax added by the said plugin

In WooCommerce how can I make it so users can only buy 1 product per order and make it so on a specific product they can only buy it once per user?

I'm building a ticketing website for events. I'm using WooCommerce and The Events Calendar plugin.
I've already made it so that users must be logged in to buy a ticket (product).
Then I found this code snippet that would limit it so that only 1 product can be purchased per order
add_filter( 'woocommerce_add_to_cart_validation', 'wc_limit_one_per_order', 10, 2 );
function wc_limit_one_per_order( $passed_validation, $product_id ) {
if ( 31 !== $product_id ) {
return $passed_validation;
}
if ( WC()->cart->get_cart_contents_count() >= 1 ) {
wc_add_notice( __( 'This product cannot be purchased with other products. Please, empty your cart first and then add it again.', 'woocommerce' ), 'error' );
return false;
}
return $passed_validation;
}
This would work, but in the first if statement you can see that the product ID has to be specified. I know I can also change this to an array like if ( ! in_array( $product_id, array( 31, 32, 33 ) ) ) { but the problem is that I would need to keep updating the IDs for every new event. Is there a way to do this so it applies to all products all the time? If not with code then maybe with settings or a plugin?
I also need to prevent customers (users) from returning to the site later and buying another ticket. So, I need to limit specific products so that only 1 of that SKU can be purchased per user account forever, meaning they can't just return to the site and start the buying process again. Is there a way to do this?
Many thanks in advance.
Is there a way to do this so it applies to all products all the time?
Sure. Just force the Cart to empty before adding a new item:
add_filter( 'woocommerce_add_to_cart_validation', 'bbloomer_only_one_in_cart', 9999, 2 );
function bbloomer_only_one_in_cart( $passed, $added_product_id ) {
wc_empty_cart();
return $passed;
}
Source and screenshot: https://www.businessbloomer.com/woocommerce-allow-1-product-cart/
I need to limit specific products so that only 1 of that SKU can be
purchased per user account forever, meaning they can't just return to
the site and start the buying process again
As #7uc1f3r said, please share the code you tried with and then we'll take a look

Disable a woocommerce delivery method on weekends and cut off time in the week

Based on Hide specific shipping method depending on day time in WooCommerce answer code, I am looking to only allow Monday to Friday before 3pm.
//hide shipping method based on time
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_time', 10, 2 );
function hide_shipping_method_based_on_time( $rates, $package )
{
// Set your default time zone (http://php.net/manual/en/timezones.php)
date_default_timezone_set('Europe/London');
// Here set your shipping rate Id
$shipping_rate_id = 'flat_rate:29';
// When this shipping method is available and after 2 PM
if ( array_key_exists( $shipping_rate_id, $rates ) && date('H') > 14 ) {
unset($rates[$shipping_rate_id]); // remove it
}
return $rates;
}
You will use the date() function with N parameter to handle the day of the week and H parameter to handle hours as follow to disable a specific shipping method on weekends and after 3 PM the weekdays:
// Hide shipping method based on the day of the week and time
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_day_of_the_week_and_time', 10, 2 );
function hide_shipping_method_based_on_day_of_the_week_and_time( $rates, $package )
{
// Set your default time zone (http://php.net/manual/en/timezones.php)
date_default_timezone_set('Europe/London');
// Here set your shipping rate Id
$shipping_rate_id = 'flat_rate:29';
// When this shipping method is available and after 2 PM
if ( array_key_exists( $shipping_rate_id, $rates )
&& ! ( date('H') <= 15 && ! in_array(date('N'), [6,7]) ) ) {
unset($rates[$shipping_rate_id]); // remove it
}
return $rates;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Clearing shipping caches:
You will need to empty your cart, to clear cached shipping data
Or In shipping settings, you can disable / save any shipping method, then enable back / save.

Woocommerce tax based on subtotal amount [duplicate]

In My Wordpress e-commerce web site I use WP Hotel Booking, a plugin for hotel room bookings. The checkout process is done using WooCommerce.
The Issue: We have different rooms with different pricing.For example :
Room A price - 1500
Room B Price - 2700
Room c price - 2200
GST Tax is set at 12% for rooms wich price is below 2500 and 18% for rooms above 2500.
Since I am using WP Hotel Booking for this custom product (room Management), I am unable to use the Additional Tax Classes option in woocommerce to set different tax classes.
I need your help in writing a function to check the room value and then decide what tax needs to be set for the given room.
Thanks
This is something accessible and easy.
1°) you need to create in your WooCommerce Tax settings 2 new Tax classes. In this example I have named that tax classes "Tax 12" and "Tax 18". Then for each of them you will have to set a different percentage of 12% and 18%.
2°) Now here is a custom function hooked in woocommerce_before_calculate_totals action hook that is going to apply a tax class based on the product price. I don't use the tax class names, but the tax class slugs, that are in lowercase and spaces are replace by a hyphen.
So Here is that code:
add_action( 'woocommerce_before_calculate_totals', 'change_cart_items_prices', 10, 1 );
function change_cart_items_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
foreach ( $cart->get_cart() as $cart_item ) {
// get product price
$price = $cart_item['data']->get_price();
// Set conditionaly based on price the tax class
if ( $price < 2500 )
$cart_item['data']->set_tax_class( 'tax-12' ); // below 2500
if ( $price >= 2500 )
$cart_item['data']->set_tax_class( 'tax-18' ); // Above 2500
}
}
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 on WooCommerce version 3+

Resources