Woocommerce Zone Based minimum Amount - wordpress

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 );

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'
);
}
}
}

Woocommerce : programmatically set a discount for the first item ordered, but inventory based

I'm building a website where i'll sell some fine art prints and i would like to set an automated discount when a customer buy the first print of a serie. Each of my prints are limited to 15 pieces and i would like to set a 30% discount for the first sell (#1/15) of each series. Then, for the next prints (#2 to #15), price goes back to normal.
Edit :
I did progress on my problem ! I did some research and tried a lot of different things and i found how to set the custom price i wanted on my product page (regular price + discount price) with the rule to only apply it if the related item available stock is 15.
regular price + discount price
And here's the code is used :
// Generating the product "regular price"
add_filter( 'woocommerce_product_get_regular_price', 'dynamic_regular_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_regular_price', 'dynamic_regular_price', 10, 2 );
function dynamic_regular_price( $regular_price, $product ) {
$stock_qte = $product->get_stock_quantity();
if( empty($regular_price) || $regular_price == 0 )
return $product->get_price();
else
return $regular_price;
}
// Generating the product "sale price"
add_filter( 'woocommerce_product_get_sale_price', 'dynamic_sale_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_sale_price', 'dynamic_sale_price', 10, 2 );
function dynamic_sale_price( $sale_price, $product ) {
$stock_qte = $product->get_stock_quantity();
if( $stock_qte == '15')
return $product-> get_regular_price() * 0.7;
else
//return $product->get_regular_price();
return $regular_price;
};
// Displayed formatted regular price + sale price
add_filter( 'woocommerce_get_price_html', 'dynamic_sale_price_html', 20, 2 );
function dynamic_sale_price_html( $price_html, $product ) {
$stock_qte = $product->get_stock_quantity();
if( $stock_qte == '15')
$price_html = wc_format_sale_price( wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ), wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) ) ) . $product->get_price_suffix();
else
$price_html = wc_price(wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ). $product->get_price_suffix());
return $price_html;
}
It's almost working but the code related to the cart values updates is not fully working. The cart sub-total is good and take count of the discount but the individual price of each product is not updated and shown as without discount. It's the same on the cart page.
cart (from mini cart)
cart (cart page)
add_action( 'woocommerce_before_calculate_totals', 'alter_price_cart', 9999 );
function alter_price_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// IF CUSTOMER NOT LOGGED IN, DONT APPLY DISCOUNT
//if ( ! wc_current_user_has_role( 'customer' ) ) return;
// LOOP THROUGH CART ITEMS & APPLY 30% DISCOUNT
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$price = $product->get_price();
$cart_item['data']->set_price( $price * 0.7 );
}
}
I'll also have to add the stock availability logic for the mini-cart / cart / checkout page but i'll do that in a second time.
I must have made some mistakes in the loop throught the cart but i cannot catch the issue :( Any idea about how to hook the price of each product and change the displayed value ?
Have a nice day,
Quentin

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 );

How would I make this role specific?

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' );
}
}
}
}

Set max weight per cart item in Woocommerce

How can I set the maximum weight per product (not per order)?
The customer can buy any number (quantity) of products until the max weight is reached. If he buys 5 products, The weight of total unit of each product cant reach max weight. There can be many products in an order but Total units(quantity) per product has Max weight.
For example, In a single order:
3 units of product A (weighing total 2kg)
5 units of product B (weighing total 1.4kg)
3 units of product C (weighing total 2kg)
In this example, the hooked function is triggered on add to cart action and you can perform all kind of checks to validate or not the action (and display a custom error message).
So you will see that you can target the total item weight individually…
add_filter( 'woocommerce_add_to_cart_validation', 'custom_add_to_cart_validation', 20, 5 );
function custom_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = '', $variations = '' ) {
// HERE define the weight limit per item
$weight_limit = 2; // 2kg
$total_item_weight = 0;
// Check cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
$item_product_id = empty($variation_id) ? $product_id : $variation_id;
// If the product is already in cart
if( $item_product_id == $cart_item['data']->get_id() ){
// Get total cart item weight
$total_item_weight += $cart_item['data']->get_weight() * $cart_item['quantity'];
}
}
// Get an instance of the WC_Product object
$product = empty($variation_id) ? wc_get_product($product_id) : wc_get_product($variation_id);
// Get total item weight
$total_item_weight += $product->get_weight() * $quantity;
if( $total_item_weight > $weight_limit ){
$passed = false ;
$message = __( "Custom warning message for weight exceed", "woocommerce" );
wc_add_notice( $message, 'error' );
}
return $passed;
}
You will need also an additional hooked function that will be triggered on cart item quantity change:
add_filter( 'woocommerce_after_cart_item_quantity_update', 'limit_cart_item_quantity', 20, 4 );
function limit_cart_item_quantity( $cart_item_key, $new_quantity, $old_quantity, $cart ){
// HERE define the weight limit per item
$weight_limit = 2; // 2kg
// Get an instance of the WC_Product object
$product = $cart->cart_contents[ $cart_item_key ]['data'];
$product_weight = $product->get_weight(); // The product weight
// Calculate the limit allowed max quantity from allowed weight limit
$max_quantity = floor( $weight_limit / $product_weight );
// If the new quantity exceed the weight limit
if( ( $new_quantity * $product_weight ) > $weight_limit ){
// Change the quantity to the limit allowed max quantity
$cart->cart_contents[ $cart_item_key ]['quantity'] = $max_quantity;
// Add a custom notice
$message = __( "Custom warning message for weight exceed", "woocommerce" );
wc_add_notice( $message, 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Resources