How would I make this role specific? - woocommerce

I am trying to make the following role-specific but it applies to every role in WooCommerce. What am I doing wrong?
add_action( 'woocommerce_check_cart_items', 'spyr_set_min_num_products' );
function spyr_set_min_num_products() {
if( is_cart() || is_checkout() ) {
global $woocommerce;
$targeted_role = 'wholesale';
$minimum_num_products = 50;
$cart_num_products = WC()->cart->cart_contents_count;
if( $cart_num_products < $minimum_num_products ) {
// Display our error message
wc_add_notice( sprintf( '<strong>A Minimum of %s products is required for wholesale accounts before checking out.</strong>'
. '<br />Current number of items in the cart: %s.',
$minimum_num_products,
$cart_num_products ),
'error' );
}
}
}

// Set a minimum number of products requirement before checking out
add_action( 'woocommerce_check_cart_items', 'spyr_set_min_num_products' );
function spyr_set_min_num_products() {
// Only run in the Cart or Checkout pages & userrole matches
if( is_cart() || is_checkout() ) {
// Check current user role
$user = wp_get_current_user();
$roles = ( array ) $user->roles;
if ( empty($roles) ) {
$roles[] = 'guest';
}
if ( in_array( 'wholesale', $roles ) ) {
global $woocommerce;
// Set the minimum number of products before checking out
$minimum_num_products = 50;
// Get the Cart’s total number of products
$cart_num_products = WC()->cart->cart_contents_count;
// Compare values and add an error is Cart’s total number of products
// happens to be less than the minimum required before checking out.
// Will display a message along the lines of
// A Minimum of 20 products is required before checking out. (Cont. below)
// Current number of items in the cart: 6
if( $cart_num_products < $minimum_num_products ) {
wc_add_notice( sprintf( '<strong>A Minimum of %s products is required for wholesale accounts before checking out.</strong>'
. '<br />Current number of items in the cart: %s.',
$minimum_num_products,
$cart_num_products ),
'error' );
}
}
}
}

Related

Problem with wordpress + woocommerce and minimum order but except local pickup

Found a code for my exact problem and used it , while it works perfect for minimum order for some reason it does not work for when choosing local pickup.
my current shipping setup:
and the website is papabross.gr
I used this code:
add_action( 'woocommerce_check_cart_items', 'wc_minimum_required_order_amount' ); function wc_minimum_required_order_amount() {
// HERE Your settings
$minimum_amount = 25; // The minimum cart total amount
$shipping_method_id = 'local_pickup:10'; // The targeted shipping method Id (exception)
// Get some variables
$cart_total = (float) WC()->cart->total; // Total cart amount
$chosen_methods = (array) WC()->session->get( 'chosen_shipping_methods' ); // Chosen shipping method rate Ids (array)
// Only when a shipping method has been chosen
if ( ! empty($chosen_methods) ) {
$chosen_method = explode(':', reset($chosen_methods)); // Get the chosen shipping method Id (array)
$chosen_method_id = reset($chosen_method); // Get the chosen shipping method Id
}
// If "Local pickup" shipping method is chosen, exit (no minimun is required)
if ( isset($chosen_method_id) && $chosen_method_id === $shipping_method_id ) {
return; // exit
}
// Add an error notice is cart total is less than the minimum required
if ( $cart_total < $minimum_amount ) {
wc_add_notice( sprintf(
__("Η ελάχιστη παραγγελία για αποστολή είναι %s (Η παραγγελία σας μέχρι στιγμής είναι %s).", "woocommerce"), // Text message
wc_price( $minimum_amount ),
wc_price( $cart_total )
), 'error' );
}
}
Not really sure if I am choosing the correct shipping id? Can I use another hook maybe?
I have used a working code I found here and everything works but the local pickup. It still asks for a minimum order.
I wonder if I have used the shipping id wrongly?
After a long search, I found a code that works! I am sharing this in case someone gets the same problem:
// Set a minimum amount of order based on shipping zone & shipping method before checking out.
add_action( 'woocommerce_check_cart_items', 'cw_min_num_products' );
// Only run in the Cart or Checkout pages.
function cw_min_num_products() {
if ( is_cart() || is_checkout() ) {
global $woocommerce;
// Set the minimum order amount, shipping zone & shipping method before checking out.
$minimum = 25;
$county = array( 'GR' );
$chosen_shipping = WC()->session->get( 'chosen_shipping_methods' )[0];
$chosen_shipping = explode( ':', $chosen_shipping );
// Defining var total amount.
$cart_tot_order = WC()->cart->subtotal;
// Compare values and add an error in Cart's total amount.
// happens to be less than the minimum required before checking out.
// Will display a message along the lines.
if ( $cart_tot_order < $minimum && in_array( WC()->customer->get_shipping_country(), $county ) && $chosen_shipping[0] != 'local_pickup' ) {
// Display error message.
wc_add_notice(
sprintf(
'Δεν έχετε φτάσει ακόμη το ελάχιστο ποσό παραγγελίας των %s€.' . '<br/>Δεν υπάρχει ελάχιστη παραγγελία εάν επιλέξετε την παραλαβή από το κατάστημα.'
. '<br />Το τρέχον ποσό της παραγγελίας σας είναι : %s€.',
$minimum,
$cart_tot_order
),
'error'
);
}
}
}

Prevent WooCommerce checkout if minimum quantity for a category is not reached unless another category is added

I am doing a check in the cart to apply a rule that if a item from the chilled category is added, a minimum of 3 chilled category items are required to check out. - This works.
However, if an item from the bundles category is also added, then the above chilled rule should not be enforced.
e.g. Minimum of 3 chilled category items required, unless a bundle item is in the cart, in which case, disregard the chilled rule.
I have the minimum 3 chilled rule working, but I can't get the code to exclude this rule if a item from the bundles category is detected?
Based on Prevent WooCommerce checkout if minimum quantity for a specific category is not reached answer code, this is my attempt:
function action_woocommerce_check_cart_items() {
// Only run on the cart or checkout pages
if ( is_cart() || is_checkout() ) {
// Minimum
$minimum = 3;
// Category
$category = 'chilled';
$category2 = 'bundles';
// Initialize
$total = 0;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Product id
$product_id = $cart_item['product_id'];
// Has certain category
if ( has_term( $category, 'product_cat', $product_id ) ) {
// Add to total
$total += $cart_item['quantity'];
}elseif (has_term ($category2, 'product_cat', $product_id)) {
break;
}
}
// When total is greater than 0 but less than the minimum
if ( $total > 0 && $total < $minimum ) {
// Notice
wc_add_notice( sprintf( __( '<strong>A minimum of %s products are required from the CHILLED category before checking out.</strong>', 'woocommerce' ), $minimum ), 'error' );
// Optional: remove proceed to checkout button
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
}
}
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );
End the execution in the current loop will not suffice, you also need to add an extra rule to the if condition.
So you get:
function action_woocommerce_check_cart_items() {
// Only run on the cart or checkout pages
if ( is_cart() || is_checkout() ) {
// Minimum
$minimum = 3;
// Category
$category = 'chilled';
$category_2 = 'bundles';
// Initialize
$total = 0;
$flag = true;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Product id
$product_id = $cart_item['product_id'];
// Has certain category
if ( has_term( $category, 'product_cat', $product_id ) ) {
// Add to total
$total += $cart_item['quantity'];
// Has other category
} elseif ( has_term( $category_2, 'product_cat', $product_id ) ) {
// Break loop
$flag = false;
break;
}
}
// When total is greater than 0 but less than the minimum & flag is still true
if ( ( $total > 0 && $total < $minimum ) && $flag ) {
// Notice
wc_add_notice( sprintf( __( 'A minimum of %s products are required from the %s category before checking out.', 'woocommerce' ), $minimum, $category ), 'error' );
// Optional: remove proceed to checkout button
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
}
}
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );

Add the values of product meta as fee in WooCommerce cart

In Italy there is a specific fee for the disposal of electronic products that must be paid during the purchase.
This "ecofee" is specific for each product.
I have set up a specific meta for each product called meta_product_grossecofee
I'd like to convert the value of this meta field in a fee on the cart.
This is the code I've tried, however without the desired result. Any advice?
add_action( 'woocommerce_cart_calculate_fees', 'ecofee_display' );
function ecofee_display(){
global $product;
$ecofee = $product->get_meta('meta_product_grossecofee');
if ($ecofee) {
WC()->cart->add_fee(__('Ecofee: ', 'txtdomain'), $ecofee);
}
}
The cart can contain multiple products, so global $product is not applicable here.
Instead, you can go through the cart and for each product for which the meta exists, add the value for this to the fee.
If the $fee is greater than 0, you can then apply it.
So you get:
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Initialize
$fee = 0;
// Loop through cart contents
foreach ( $cart->get_cart_contents() as $cart_item ) {
// Get meta
$ecofee = $cart_item['data']->get_meta( 'meta_product_grossecofee', true );
// NOT empty & variable is a number
if ( ! empty ( $ecofee ) && is_numeric( $ecofee ) ) {
// Addition
$fee += $ecofee;
}
}
// If greater than 0
if ( $fee > 0 ) {
// Add additional fee (total)
$cart->add_fee( __( 'Ecofee', 'woocommerce' ), $fee, false );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
Note: if you want to take into account the quantity per product:
Replace
// NOT empty & variable is a number
if ( ! empty ( $ecofee ) && is_numeric( $ecofee ) ) {
// Addition
$fee += $ecofee;
}
With
// NOT empty & variable is a number
if ( ! empty ( $ecofee ) && is_numeric( $ecofee ) ) {
// Get product quantity in cart
$quantity = $cart_item['quantity'];
// Addition
$fee += $ecofee * $quantity;
}

Apply discount based on user role when they buy x quantity of specific product category in WooCommerce

I want to give discount for my customer based user role ex:
for user role (subscriber) 50% discount if they buy 25 products from a specific category.
If use a snippet but it is not cover the second part of my question (25 products from a specific category).
// Applying conditionally a discount for a specific user role
add_action( 'woocommerce_cart_calculate_fees', 'discount_on_user_role', 20, 1 );
function discount_on_user_role( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return; // Exit
// Only for 'company' user role
if ( ! current_user_can('company') )
return; // Exit
// HERE define the percentage discount
$percentage = 50;
$discount = $cart->get_subtotal() * $percentage / 100; // Calculation
// Applying discount
$cart->add_fee( sprintf( __("Discount (%s)", "woocommerce"), $percentage . '%'), -$discount, true );
}
Any advice?
For the category categorie-1 (adjust if desired) you can use a counter based on the product quantity in the cart.
When this is equal to 25 or more you can apply the discount.
So you get:
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Only for 'company' user role
if ( ! current_user_can( 'company' ) )
return;
// Category
$category = 'categorie-1';
// Percentage discount
$percentage = 50; // 50%
// Min quantity
$minimun_quantity = 25;
// Initialize
$current_quantity = 0;
$current_total = 0;
// Loop though each cart item
foreach ( $cart->get_cart() as $cart_item ) {
// Has certain category
if ( has_term( $category, 'product_cat', $cart_item['product_id'] ) ) {
// Get quantity
$product_quantity = $cart_item['quantity'];
// Add to quantity total
$current_quantity += $product_quantity;
// Get price
$product_price = $cart_item['data']->get_price();
// Add to current total
$current_total += $product_price * $product_quantity;
}
}
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Calculation
$discount = $current_total * $percentage / 100;
// Applying discount
$cart->add_fee( sprintf( __( 'Discount (%s)', 'woocommerce' ), $percentage . '%'), -$discount, true );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );

Woocommerce Zone Based minimum Amount

How Can ı set this situation ?
How can i add minimum order limit to flat rate product by zone ?
we can only free shipping products.
You can use the following for this, based on the zone id
function zone_based_minimum_amount() {
// Only run it in Cart or Checkout pages
if( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ) {
// HERE below your targeted zone IDs
$targeted_zones_ids = array( 1, 2 );
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); // The chosen shipping mehod
$chosen_method = explode(':', reset($chosen_methods) );
$shipping_zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $chosen_method[1] );
$zone_name = $shipping_zone->get_zone_name(); // Get the zone name
$zone_id = $shipping_zone->get_id(); // Get the zone ID
// Total (before taxes and shipping charges)
$total = WC()->cart->subtotal;
// HERE Set minimum cart total amount
$min_total = 100;
// Add an error notice is cart total is less than the minimum required
if( $total <= $min_total && in_array( $zone_id, $targeted_zones_ids ) ) {
// Display an error message
wc_add_notice( '<strong>' . sprintf(
__("A minimum total purchase amount of %s is required to checkout."),
wc_price($min_total)
) . '<strong>', 'error' );
// Removing the Proceed to checkout button from the Cart page
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
}
}
add_action( 'woocommerce_check_cart_items', 'zone_based_minimum_amount', 10, 0 );

Resources