I need to set up shipping price like this:
1 - 5 qty for $60
6 - 10 qty for $90
How can I do this? So if someone buys 3 pieces from the product then is charged 60 for shipping, if 6 or more then 90.
The basic [qty] placeholder woocommerce provides can't do this and did not find any plugin that can do it.
Maybe something like this ? Add following function in your active theme functions.php file
add_filter( 'woocommerce_package_rates', 'custom_shipping_costs', 20, 2 );
function custom_shipping_costs( $rates, $package ) {
global $woocommerce;
$qty = $woocommerce->cart->cart_contents_count;
//error_log($qty);
foreach( $rates as $rate_key => $rate ){
// Excluding free shipping methods
if( $rate->method_id != 'free_shipping'){
// Between 1 and 5
if($qty > 0 && $qty <= 5):
$rates[$rate_key]->cost = '60';
// Between 6 and 10
elseif($qty > 5 && $qty <= 10):
$rates[$rate_key]->cost = '90';
else:
// For over 10
$rates[$rate_key]->cost = '60';
endif;
}
}
return $rates;
}
Related
The discount I currently have essentially says
If 6 products within a specific category are in the cart --- discount the total price of $10
This piece of the code works fine. My issue is, this does not work
If there are 7 products, the 7th product being from a different category.
My goal is to give the discount no matter how many products are in the cart so long as there are 6 products within "Category A".
The following code works so long as there is 6 products in the "discounted category" or there is 1 product with a quantity of 6 etc. It falls apart when I add a product from another category. Feel free to rip it apart.
add_action( 'woocommerce_before_calculate_totals', 'this_item_free' );
function this_item_free() {
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$valid_product_category_id = array('soup-mix');
$has_category = false;
$count = WC()->cart->get_cart_contents_count();
foreach ( WC()->cart->get_cart() as $product ) {
$quantity = $product['quantity'];
$price = $product['data']->get_price();
}
if ( has_term( $valid_product_category_id, 'product_cat', $product['product_id'],
$product['quantity'] ) ) {
$has_category = true;
$cart_total = floatval( preg_replace( '#[^\d.]#', '', WC()->cart->get_cart_total() ) );
if($count == 6 && $has_category = true){
add_action( 'woocommerce_cart_calculate_fees', 'discount_based_on_total', 25, 1 );
function discount_based_on_total( $cart ) {
$total = $cart->cart_contents_total;
$discount = 9.95;
$cart->add_fee( __('discount', 'woocommerce'), -$discount );
wc_add_notice( apply_filters( 'discount_applied', 'You just got a free soup!') );
}
}
}
}
Your code contains some unnecessary steps and what you want to achieve can be obtained with just the woocommerce_cart_calculate_fees action hook
My answer contains:
Give a discount no matter how many products are in the cart so long as there are 6 products or there is 1 product with a quantity of 6, etc.. within "Category A".
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
/* SETTINGS */
// Specific categories
$specific_categories = array( 'Categorie-A' );
// Discount
$discount = 10;
// Min quantity
$minimun_quantity = 6;
/* END SETTINGS */
// Counter
$current_quantity = 0;
// Loop though each cart item
foreach ( $cart->get_cart() as $cart_item ) {
// Get product id
$product_id = $cart_item['product_id'];
// Has certain category
if ( has_term( $specific_categories, 'product_cat', $product_id ) ) {
// Quantity
$product_quantity = $cart_item['quantity'];
// Add to total
$current_quantity += $product_quantity;
}
}
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
To apply the discount per 6 products (6 = $10, 12 = $20, 18 = $30, etc..)
Replace
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
With
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Modulo
$mod = $current_quantity % $minimun_quantity;
// Times it fit
$times = ( $current_quantity - $mod ) / $minimun_quantity;
// Discount * times
$discount = $discount * $times;
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
I wish to set up a specific discount on a particular variable products but for certain selected variations not for all variation:
eg : my varible id - 1571
variation id - 1572
variation id - 1573
So if customer buys one product they get the another (the same) on 50% discount (Buy one get another for 50% off).
I've tried many discount plugins and the closest that I have found are:
Pricing Deals for WooCommerce,
Conditional Discounts for WooCommerce
WooCommerce Extended Coupon Features FREE
With some of them, I was able to setup discount on subtotal or discount on a each product but not exactly what I am looking for (Buy 1 get 1 off). There are other pro plugins I don't want to go for it.
The nearest code that I found is WooCommerce discount: buy one get one 50% off with a notice.
Is it possible to make a discount on the 2nd item for specific product variations of a variable product (only for each product variation)?
mak
To get a 50% Off on the 2nd item for some specific product variations of a variable product, you will use the following instead:
add_action('woocommerce_cart_calculate_fees', 'add_custom_discount_2nd_at_50', 10, 1 );
function add_custom_discount_2nd_at_50( $cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// YOUR SETTINGS:
$product_variations_ids = array(1572, 1573); // <== HERE your targeted product variations
// Initializing variables
$discount = 0;
$product_names = array();
// Loop through cart items
foreach ( $cart->get_cart() as $key => $cart_item ) {
if ( in_array( $cart_item['variation_id'], $product_variations_ids ) ) {
$qty = (int) $cart_item['quantity'];
$price = (float) $cart_item['data']->get_price();
$name = (string) $cart_item['data']->get_name();
if ( $qty > 1 ) {
$discount -= number_format( $price / 2, 2 );
}
elseif( $qty = 1 ) {
$product_names[] = $name;
}
}
}
// Applying the discount
if( $discount != 0 ){
$cart->add_fee('Buy one get one 50% off', $discount );
}
// Display a custom reminder notice on cart page (otional)
if( ! empty($product_names) ){
wc_clear_notices(); // clear other notices on checkout page.
if( ! is_checkout() ){
wc_add_notice( sprintf(
__( "Add one more to get 50%% off on the 2nd item for %s" ),
'"<strong>' . implode(', ', $product_names) . '</strong>"'
), 'notice' );
}
}
}
Code goes in functions.php file of your active child theme (or active theme) Tested and works.
To get 1 item at 50% OFF for each item purchased, instead of 50% OFF on the 2nd item, replace:
$discount -= number_format( $price / 2, 2 );
by:
$multiplier = ( $qty % 2 ) === 0 ? $qty / 2 : ( $qty - 1 ) / 2;
$discount -= number_format( $price / 2 * $multiplier, 2 );
To get the 2nd one Free instead of 50% OFF on the 2nd item, replace the code line:
$discount -= number_format( $price / 2, 2 );
by:
$discount -= $price;
To get 1 item free for each item purchased, instead of 50% OFF on the 2nd item, replace:
$discount -= number_format( $price / 2, 2 );
by:
$multiplier = ( $qty % 2 ) === 0 ? $qty / 2 : ( $qty - 1 ) / 2;
$discount -= $price * $multiplier;
You were really close!
The discount amount calculation were wrong
add_action('woocommerce_cart_calculate_fees', 'add_custom_discount_2nd_at_50', 10, 1 );
function add_custom_discount_2nd_at_50( $wc_cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$discount = 0;
$items_prices = array();
$qty_notice = 0; // <== Added HERE
// Set HERE your targeted variable product ID
$targeted_product_id = 1571 ;
foreach ( $wc_cart->get_cart() as $key => $cart_item ) {
if( $cart_item['product_id'] == $targeted_product_id ){
$qty = intval( $cart_item['quantity'] );
$qty_notice += intval( $cart_item['quantity'] ); // <== Added HERE
for( $i = 0; $i < $qty; $i++ )
$items_prices[] = floatval( $cart_item['data']->get_price());
}
}
$count_items_prices = count($items_prices);
//to get the discount of lowest price sorting in descending order
rsort($items_prices);
if( $count_items_prices > 1 ) foreach( $items_prices as $key => $price )
if( $key % 2 == 1 ) $discount -= number_format($price / 2, 2 );
if( $discount != 0 ){
// The discount
# Note: Last argument in add_fee() method is related to applying the tax or not to the discount (true or false)
$wc_cart->add_fee('50% off de segunda almohada' , (($price/2)*($discount))^⁻1, true ); //EDITED
// Displaying a custom notice (optional)
wc_clear_notices();
if(!is_checkout()){
wc_add_notice( __("Hurrah!! You got 50% off discount on the 2nd item"), 'notice');
}}
// Display a custom notice on cart page when quantity is equal to 1.
elseif( $qty_notice == 1){
wc_clear_notices();
if(!is_checkout()){
wc_add_notice( __( "Add one more to get 50% off on 2nd item" ), 'notice');
}}
}
I'd like to use Woocommerce over WordPress for my shop, but clients should be able to buy the product by either unit or weight.
If X units were bought, we must measure the actual weight of the purchase (obtained during the picking and packing of the order), and adjust the price accordingly.
Is there an easy way to do this on Woocommerce?
Thanks
You can do your modification using follows code snippet -
function adjust_price_based_on_weight( $cart_object ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = $cart_item['data'];
$product_id = $cart_item['product_id'];
$quantity = $cart_item['quantity'];
$product_price = floatval( $_product->get_price() ); // Actual product price
// Do your calculation based on product quantity and weight
// for example suppose product per unit weight 2 kgs and add to cart number of unit is 3.
$product_unit_weights = $quantity * 2; // where 2kg/per unit and $quantity is 3
if( $product_unit_weights > 5 ) { // if units weights is greter than 5 kgs additional cost 10.
$additionalPrice = 10;
$_product->set_price( $product_price + $additionalPrice );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'adjust_price_based_on_weight', 99 );
I'm trying to setup no tax for orders under $110.
I bumped into this thread Set different Tax rates conditionally based on cart item prices in Woocommerce and tried it but doesn't seems to work when i add it on functions.php - Maybe because some of the codes are outdated?
Here's the revised 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 < 111 )
$cart_item['data']->set_tax_class( 'zero-rate' ); // below 111
if ( $price >= 111 )
$cart_item['data']->set_tax_class( 'standard' ); // Equal above 110
}
}
I believe Standard & Zero rates tax options in Woo commerce > Settings > Tax are setup correctly.
Got it working using this code:
add_action( 'woocommerce_before_calculate_totals', 'apply_conditionally_zero_tax_rate', 10, 1 );
function apply_conditionally_zero_tax_rate( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$defined_amount = 110;
$subtotal = 0;
// Loop through cart items (1st loop - get cart subtotal)
foreach ( $cart->get_cart() as $cart_item ) {
$subtotal += $cart_item['line_total'];
}
// Targeting cart subtotal up to the "defined amount"
if ( $subtotal > $defined_amount )
return;
// Loop through cart items (2nd loop - Change tax rate)
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_tax_class( 'zero-rate' );
}
}
My woocommerce products are actually cruise expeditions (two products = two expedition types). For each product, the variations consists of the weeks in which cruises take place (= dates).
So I have Ligurian Sea Expeditions with 20 different weeks and Greece Expeditions with other 20 weeks. Fortunately I have just 2 products like that to deal with (a very simple situation)
The customer usually chooses one week expedition. However I need to apply a 10% discount on the second (or third) week in case a customer decides to apply for > 1 week. Hence the first week is paid full price, but the second and (in case there is) the third week will be discounted 10%.
I have come out with a function that enables to apply the discount in the case of two weeks.
function cart_discount() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
global $woocommerce; $cat_count = 0;
$cart = WC()->cart->get_cart();
foreach($cart as $cart_item_key => $values) {
$product_id = $values['product_id']; // product ID (= cruise type)
$variation_id = $values['variation_id']; // variation (=week)
$cart_lines_total = $values["line_total"]; //variation total price
$cart_lines_quantity = $values["quantity"];// variation quantity
//$product = 1394 = Expedition Ligurian eng
//$product = 1389 = Expedition Greece eng
//$product = 13888 = Expedition Ligurian ita
//$product = 13910 = Expedition Greece ita
//I hereby add a condition as we do have the same cruises with students prices which are not eligible to this discount (and are stored with different product_id)
if($product_id == '1394' || $product_id == '1389' || $product_id == '13888' || $product_id == '13910')
{
//put in a new array only the terms I need for the calculation later
$cart_array []= array( $product_id , $variation_id, $cart_lines_quantity, $cart_lines_total);
}
}
// discount percent is 10%
$percent = -0.10;
if ($cart_array[0][0] == $cart_array[1][0]) //if in the cart the same product is present two times
{
$discount = $percent * $cart_array[1][2] * $cart_array[1][3];
$discount_text = __( 'Quantity discount', 'woocommerce' );
WC()->cart->add_fee( $discount_text, $discount, false );
}
}
add_action( 'woocommerce_cart_calculate_fees','cart_discount' );
This code has many limitations as I said before, as it doesn't take in acccount some scenarios such as:
1) it deals only if in the cart tere are only two variations of the same product: in case a customer decides for x weeks to be purchased I should be able to check if the same product is present with > 2 variations;
2) It doesn't take into account the possibility having the two products with 2 ore more variations (ie.a person buying let's say two weeks in Ligurian Sea and two weeks in Greece)
If somebody can help me in improving the code I wrote I would be very happy!!
Just to make sure i got it right, you want to apply a discount if the customer buys more than 1 variation of the same product. Correct?
Here is the final code I wrote (it works, I have tested it)
function cart_discount() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
global $woocommerce;
$cart = WC()->cart->get_cart();
$has_coupons = count(WC()->cart->applied_coupons)>0?true:false;
if(!$has_coupons) //verifies that other discounts are not added
{
foreach($cart as $cart_item_key => $values) {
$product_id = $values['product_id']; // product ID
$variation_id = $values['variation_id']; // product quantity
$cart_lines_total = $values["line_total"];
$cart_lines_quantity = $values["quantity"];
//products for which this kind of discount must be applicable:
//$product_id = 1394 = Spedizioni CSR eng
//$product_id = 1389 = Spedizioni IDP eng
//$product_id = 13888 = Spedizioni CSR ita
//$product_id = 13910 = Spedizioni IDP ita
if($product_id == '1394' || $product_id == '1389' || $product_id == '13888' || $product_id == '13910')
{
$cart_array []= array( $product_id , $variation_id, $cart_lines_quantity, $cart_lines_total);
}
}
$conteggio = count($cart_array); //conta il numero di prodotti nel carrello
// percent is 10%
$percent = -0.10;
if ($conteggio < 3 && $cart_array[0][0] == $cart_array[1][0])
{
$discount = $percent * $cart_array[1][3];
$discount_text = __( '10% discount on subsequent week(s)', 'woocommerce' );
WC()->cart->add_fee( $discount_text, $discount, false );
}
if ($conteggio < 4 && $cart_array[0][0] == $cart_array[1][0] && $cart_array[0][0] == $cart_array[2][0])
{
$discount = ($percent * $cart_array[1][3]) + ($percent * $cart_array[2][3]);
$discount_text = __( '10% discount on subsequent week(s)', 'woocommerce' );
WC()->cart->add_fee( $discount_text, $discount, false );
}
if ($conteggio < 5 && $cart_array[0][0] == $cart_array[1][0] && $cart_array[0][0] == $cart_array[2][0] && $cart_array[0][0] == $cart_array[3][0])
{
$discount = ($percent * $cart_array[1][3]) + ($percent * $cart_array[2][3]) + ($percent * $cart_array[3][3]);
$discount_text = __( '10% discount on subsequent week(s)', 'woocommerce' );
WC()->cart->add_fee( $discount_text, $discount, false );
}
} else return;
}
add_action( 'woocommerce_cart_calculate_fees','cart_discount' );
As you see, I had to specify the product_id of the products that are interested in this particular kind of discount, which is fine for me, although it would be nicier if we could set it to categories (I didn't have the time to develop that condition)
Secondly, the part I don't like is the following
if ($conteggio < 3 && $cart_array[0][0] == $cart_array[1][0])
and all the following conditions: I was looking for a function that may go through the $cart_array and find the relations thta I set manually in each if() condition.
Thanks