WooCommerce, disable shipping based on an acf field - woocommerce

I added a true/false field inside the user profile through acf.
I need to hide a specific shipment if this field is selected or not.
If selected, the shipment must be hidden.
This is my code:
function filter_woocommerce_package_rates( $rates, $package ) {
$user_id = get_current_user_id();
$verified=false;
$acf_field=get_user_meta( $user_id, 'fast_shipping', true );
if($acf_field) $verified=true;
// Loop trough
foreach ( $rates as $rate_id => $rate ) {
if ( $verified ) {
unset( $rates['flat_rate:8'] );
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
But nothing is hidden.

Can you please try below code:
function filter_woocommerce_package_rates( $rates, $package ) {
$user_id = get_current_user_id();
$verified=false;
$acf_field=get_user_meta( $user_id, 'fast_shipping', true );
if(is_bool($acf_field) == 1) $verified=true;
if ( is_bool($verified) == 1 ) {
unset( $rates['flat_rate:8'] );
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
Please let me know if you find any issues.

Related

replace existing product in cart when adding new but excluding specific products. Those specific product will be added and not gonna replaced

replace existing product in cart when adding new but excluding specific products. Those specific product will be added and not gonna replaced.
My code:
add_filter( 'woocommerce_add_cart_item_data', 'woo_custom_add_to_cart' );
function woo_custom_add_to_cart($cart_item_data) {
$product_categories = array('mid-career-package-deal','advanced-career-package-deal');
$excluded_ids = array(1105,1108);
if(! in_array( $product_categories,$excluded_ids ) ) {
WC()->cart->add_to_cart();;
}
global $woocommerce;
$woocommerce->cart->empty_cart();
// Do nothing with the data and return
return $cart_item_data;
}
add_filter( 'woocommerce_add_to_cart_validation',
'remove_cart_item_before_add_to_cart', 20, 3 );
function remove_cart_item_before_add_to_cart( $passed, $product_id,
$quantity )
{
$excluded_ids = array(1105, 1108);
if( ! WC()->cart->is_empty()&& ! in_array( $product_id, $excluded_ids
))
WC()->cart->empty_cart();
return $passed;
}

Update WooCommerce order status if product custom field is set

I need to automatically set a certain order status (different than processing) when getting a new order.
This is achieved by this function:
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) { return; }
$order = wc_get_order( $order_id );
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
This totally works. Now I only need this to happen when a product has a customization.
The way to customize a product is filling an input field before adding to cart. The input is attached to the item data:
// Add custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 10, 2 );
function add_custom_cart_item_data( $cart_item_data, $product_id ){
if( isset($_POST['custom_text']) ) {
$cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
$cart_item_data['unique_key'] = md5( microtime().rand() ); // Make each item unique
}
return $cart_item_data;
}
Then the custom text is retrieved and displayed in cart and in the order data using this:
// Display custom cart item data on cart and checkout
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_item_data, $cart_item ) {
if ( !empty( $cart_item['custom_text'] ) ){
$cart_item_data[] = array(
'name' => __('Customization', 'woocommerce'),
'value' => $cart_item['custom_text'] // Already sanitized field
);
}
return $cart_item_data;
}
// Save and display custom item data everywhere on orders and email notifications
add_action( 'woocommerce_checkout_create_order_line_item', 'add_product_custom_field_as_order_item_meta', 10, 4 );
function add_product_custom_field_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
if ( isset($values['custom_text']) ) {
$item->update_meta_data('Add on', $values['custom_text'] );
}
}
I'm trying using the if ( isset($values['custom_text']) ) part as a trigger of the function to change the order status only if the product add on is set and other similar methods (like if ( !empty( $cart_item['custom_text'] ) ) but I'm not sure this is the way to go:
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) {return;}
$order = wc_get_order( $order_id );
if ( isset($values['custom_text']) ) {
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
}
This above does nothing. Am I anywhere near it with this approach?
EDIT: I tried this too
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) {return;}
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item_id => $item ) {
$allmeta = $item->get_meta_data();
if ( isset($values['custom_text']) ) {
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
}
}
Your code contains some unnecessary steps as well as some shortcomings
For example, the woocommerce_add_cart_item_data hook contains 3 arguments versus 2
So you get:
// Add custom cart item data
function filter_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
// Isset and NOT empty
if ( isset ( $_POST[ 'custom_text' ] ) && ! empty ( $_POST[ 'custom_text' ] ) ) {
$cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data', 10, 3 );
// Display custom cart item data on cart and checkout
function filter_woocommerce_get_item_data( $cart_data, $cart_item = null ) {
if ( isset ( $cart_item['custom_text'] ) ) {
$cart_data[] = array(
'name' => __( 'Customization', 'woocommerce' ),
'value' => $cart_item['custom_text']
);
}
return $cart_data;
}
add_filter( 'woocommerce_get_item_data', 'filter_woocommerce_get_item_data', 10, 2 );
// Add the information as meta data so that it can be seen as part of the order
// Save and display custom item data everywhere on orders and email notifications
function action_woocommerce_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
if ( isset ( $values['custom_text'] ) ) {
$item->update_meta_data( 'custom_text', $values['custom_text'] );
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'action_woocommerce_checkout_create_order_line_item', 10, 4 );
// On thankyou page
function action_woocommerce_thankyou( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Only when the current order status is 'processing'
if ( $order->get_status() == 'processing' ) {
// Loop trough
foreach ( $order->get_items() as $item ) {
// Get meta
$value = $item->get_meta( 'custom_text' );
// NOT empty
if ( ! empty ( $value ) ) {
// Update status (change to desired status)
$order->update_status( 'cancelled' );
// Stop loop
break;
}
}
}
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
Currently it is just checking if the value exists, to compare it effectively
Change
// NOT empty
if ( ! empty ( $value ) ) {
// Update status
$order->update_status( 'cancelled' );
// Stop loop
break;
}
To
// Compare
if ( $value == 'some value' ) ) {
// Update status
$order->update_status( 'cancelled' );
// Stop loop
break;
}

Hide woocommerce-checkout-review-order table for specific product categories in WooCommerce cart

i would like to hide the woocommerce checkout-review-order table for specific product categories in WooCommerce cart category "X"
I'm using the code below for this, but it does not hide the table
function conditional_checkout_fields_products( $fields ) {
$cart = WC()->cart->get_cart();
foreach ( $cart as $item_key => $values ) {
$product = $values['data'];
if ( $product->id == 168 ) {
unset( $fields['order']['order_review'] );
}
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'conditional_checkout_fields_products' );
//OTHER HOOK add_filter( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
Any help with that?
To hide the woocommerce checkout-review-order table, you can use:
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
To hide the woocommerce checkout-review-order table for specific product categories in WooCommerce cart
You can use:
function action_woocommerce_checkout_order_review() {
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$categories = array( 63, 15, 'categorie-1', 'categorie-2' );
// Initialize
$flag = false;
// WC Cart
if ( WC()->cart ) {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ) {
$flag = true;
break;
}
}
}
// True
if ( $flag ) {
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
}
}
add_action( 'woocommerce_checkout_order_review', 'action_woocommerce_checkout_order_review', 5 );

Issue allow only one product in WooCommerce cart

We have a booking system which should allow only one product in the cart (when customers adds next product, previous one should be deleted from the cart).
Until today we have been using following code:
add_filter( 'woocommerce_add_to_cart_validation', 'b_only_one_in_cart', 99, 2 );
function b_only_one_in_cart( $passed, $added_product_id ) {
wc_empty_cart();
return $passed;
}
But it ceased to work (and I can't find why). Has something changed in the recent version of WooCommerce? How can I get it to work again?
You could use WC()->cart->empty_cart(); instead
function filter_woocommerce_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null, $variations = null ) {
// When NOT empty
if ( ! WC()->cart->is_empty() ) {
// Empties the cart and optionally the persistent cart too.
WC()->cart->empty_cart();
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'filter_woocommerce_add_to_cart_validation', 10, 5 );
If the above does not work for some reason, you can also apply it in the following way: (Solution for PHP 7.3 and up)
// Used to calculate totals
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Get cart
$get_cart = $cart->get_cart();
// Solution for PHP 7.3 and up
foreach ( $get_cart as $cart_item_key => $cart_item ) {
// NOT last element
if ( $cart_item_key !== array_key_last( $get_cart ) ) {
// Remove a cart item
$cart->remove_cart_item( $cart_item_key );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );

Woocommerce - custom functions runs only on update cart

I wrote a very small function to disable installation as a method (from table rate shipping plugin) if a product is not in the cart or if the quantity of that product in the cart is less than 6.
This works, but only when I click on "update cart" button and not, for example, when I click on cart.
here's the function, directly from my function.php file in my custom theme:
function disable_installation_for_less_than( $rates ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$installation = $rates['table_rate_shipping_installation'];
foreach ( $items as $item => $values ) {
$productID = $values['product_id'];
$productQuantity = $values['quantity'];
unset( $rates['table_rate_shipping_installation'] );
if ( $productID == 2412 ) {
if ( $productQuantity < 6 ) {
unset( $rates['table_rate_shipping_installation'] );
} else {
array_push($rates, $installation);
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'disable_installation_for_less_than', 10, 3 );
Any idea why? am I using the wrong hook?
Thanks for any help
Also, rather then un-setting the installation and re-set it only when needed, is there a better way to say "if this product is NOT in the cart" then remove this?
thanks
Ok, I managed to solve it this way:
function disable_installation_for_less_than( $rates ) {
global $woocommerce;
$items = $woocommerce->cart->get_cart();
$showInstallation= false;
foreach ( $items as $item => $values ) {
$productID = $values['product_id'];
$productQuantity = $values['quantity'];
if ( $productID == 2412 ) {
$showInstallation= true;
if ( $productQuantity < 6 ) {
unset( $rates['table_rate_shipping_installation'] );
}
}
}
if ($showInstallation== false){
unset( $rates['table_rate_shipping_installation'] );
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'disable_installation_for_less_than', 10, 2 );
It's working now.

Resources