I've taken this code from another post and basically this code is trying to force the cart price with a discount.
What I want to do is force the discount only if the product is on backorder. So if product is on backorder, the client can order this item which leads to a deposit calculation in the cart.
From Deposit based on a percentage of total cart amount 2nd code snippet answer, I have tried to make code changes to get a specific discount on backordered cart items.
The original code works fine as it's, but how to make it work only for backordered items?
I tried several days now using for example $product->is_on_backorder( 1 ) but I can't get it to work. How to get backordered items total amount in cart?
I know it's an easy solution, but I have tried several solutions and can't get it to work.
Updated: To make that for backordered items only, you will use the following:
add_action( 'woocommerce_cart_calculate_fees', 'calculated_deposit_discount_on_backorders' );
function calculated_deposit_discount_on_backorders( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
## Set HERE your negative percentage (to remove an amount from cart total)
$percent = -.80; // 80% off (negative)
$backordered_amount = 0;
foreach( $cart->get_cart() as $cart_item ) {
if( $cart_item['data']->is_on_backorder( $cart_item['quantity'] ) ) {
$backordered_amount = $cart_item['line_total'] + $cart_item['line_tax'];
}
}
## ## CALCULATION ## ##
$calculated_amount = $backordered_amount * $percent;
// Adding a negative fee to cart amount (Including taxes)
$cart->add_fee( __('Deposit calculation', 'woocommerce'), $calculated_amount, true );
}
Code goes in function.php file of your active child theme (or active theme). It should work.
Related
I am trying to set up a custom coupon code so that customers can add an add-on product to their cart, only if their cart total is $50 or more.
I am using Allow add to cart for specific products based on cart total in WooCommerce answer code that allows or denies adding the product depending on their cart total and this is working great.
My issue is that I have another bit of code that is supposed to delete the addon item if it's in the cart and the cart total is no longer within the threshold.
In my case I have the threshold set to $50, and the addon product costs $10.
In testing I've found that when the cart total is $60 or more, everything works fine. I can even remove a couple of items from the cart and the addon item will stay until the total is under the threshold, then it gets removed as well.
However if the cart total is anywhere between $50 and $60 when I go to add the addon item, the addon item is immediately deleted as soon as it's added.
I would expect the order of operations to go
Checks the cart total, finds that it is above $50
Allows me to add the addon item
Checks the cart total with the addon item included, finds that it is now above $60
Allows the addon to stay
Based on Add or remove specific cart Item based on WooCommerce cart total answer code, here is the code I'm using:
add_action( 'woocommerce_before_calculate_totals', 'add_or_remove_cart_items', 10, 1 );
function add_or_remove_cart_items( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ONLY for logged users (and avoiding the hook repetition)
if ( ! is_user_logged_in() && did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$threshold_amount = 50; // The threshold amount for cart total
$addon_product_id = 7039; // ID of the addon item
$addon_product_cost = 10; // Cost of addon item
$cart_items_total = 0; // Initializing
$threshold_amount_with_addon = $threshold_amount + $addon_product_cost;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// Check if the free product is in cart
if ( $cart_item['data']->get_id() == $addon_product_id ) {
$addon_item_key = $cart_item_key;
}
// Get cart subtotal incl. tax from items (with discounts if any)
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
// If cart total is below the defined amount and addon product is in cart, we remove it.
if ( $cart_items_total < $threshold_amount_with_addon && isset($addon_item_key) ) {
$cart->remove_cart_item( $addon_item_key );
return;
}
}
I can't for the life of me figure out what is going wrong. Any help would be much appreciated.
Below, we exclude the Add-On item from subtotal calculation so we don't need to add the Add-On price to threshold amount (so we keep your steps 1, 2 and 4).
The revisited code:
add_action( 'woocommerce_before_calculate_totals', 'add_or_remove_cart_items', 10, 1 );
function add_or_remove_cart_items( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// ONLY for logged users, avoiding the hook repetition
if ( ! is_user_logged_in() || did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$addon_product_id = 7039; // ID of the addon item
$threshold_amount = 50; // The threshold amount
$cart_items_total = 0; // Initializing
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ){
// For Add-On product: Check if it is in cart
if ( in_array( $addon_product_id, [$cart_item['product_id'], $cart_item['variation_id']] ) ) {
$addon_item_key = $cart_item_key;
}
// For other items: add their line total including taxes to items subtotal
else {
// Sum dicounted line total incl. taxes to get other items subtotal
$cart_items_total += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// If cart total is below the defined amount and addon product is in cart, we remove it.
if ( $cart_items_total < $threshold_amount && isset($addon_item_key) ) {
$cart->remove_cart_item( $addon_item_key );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
I am using Woocommerce set minimum order for a specific user role answer code and it works like a charm!
Though I would like to only have a minimum order amount if the product(s) placed in the shopping cart are not in stock (backorder). If the product(s) in the shopping cart are in stock, there should be no minimum order amount. Could someone help me out?
To make the code work only when there is backordered items, you need to include in the code a check for backordered items as follows:
add_action( 'woocommerce_check_cart_items', 'set_min_total_per_user_role' );
function set_min_total_per_user_role() {
// Only run in the Cart or Checkout pages
if( is_cart() || is_checkout() ) {
// Set minimum cart total (by user role)
$minimum_cart_total = current_user_can('company') ? 250 : 100;
// Total (before taxes and shipping charges)
$total = WC()->cart->subtotal;
$has_backordered_items = false;
// Check for backordered cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( $cart_item['data']->is_on_backorder( $cart_item['quantity'] ) ) {
$has_backordered_items = true;
break; // stop the loop
}
}
// Add an error notice is cart total is less than the minimum required
if( $has_backordered_items && $total <= $minimum_cart_total ) {
// Display our error message
wc_add_notice( sprintf( '<strong>Dear customer, minimum order of %s is required to make a purchase on your site.</strong> <br>
Your actual cart amount is: %s',
wc_price($minimum_cart_total),
wc_price($total)
), 'error' );
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.
Based on: Woocommerce set minimum order for a specific user role
I've taken this code from another post and basically this code is trying to force the cart price with a discount.
What I want to do is force the discount only if the product is on backorder. So if product is on backorder, the client can order this item which leads to a deposit calculation in the cart.
From Deposit based on a percentage of total cart amount 2nd code snippet answer, I have tried to make code changes to get a specific discount on backordered cart items.
The original code works fine as it's, but how to make it work only for backordered items?
I tried several days now using for example $product->is_on_backorder( 1 ) but I can't get it to work. How to get backordered items total amount in cart?
I know it's an easy solution, but I have tried several solutions and can't get it to work.
Updated: To make that for backordered items only, you will use the following:
add_action( 'woocommerce_cart_calculate_fees', 'calculated_deposit_discount_on_backorders' );
function calculated_deposit_discount_on_backorders( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
## Set HERE your negative percentage (to remove an amount from cart total)
$percent = -.80; // 80% off (negative)
$backordered_amount = 0;
foreach( $cart->get_cart() as $cart_item ) {
if( $cart_item['data']->is_on_backorder( $cart_item['quantity'] ) ) {
$backordered_amount = $cart_item['line_total'] + $cart_item['line_tax'];
}
}
## ## CALCULATION ## ##
$calculated_amount = $backordered_amount * $percent;
// Adding a negative fee to cart amount (Including taxes)
$cart->add_fee( __('Deposit calculation', 'woocommerce'), $calculated_amount, true );
}
Code goes in function.php file of your active child theme (or active theme). It should work.
I have the following functions in my WooCommerce child themes functions.php file.
But every time the cart is updated I need to reload the cart page for the functions to run.
How can I execute the functions automatically when the shopping cart is updated?
<?php
add_action( 'woocommerce_before_calculate_totals', 'add_custom_weight', 10, 1 );
function add_custom_weight( $cart ) {
if (($_SESSION["kilo_rate"]) && ($_SESSION["cart_items_count"]) > 0 ){
$each_cart_item_weight = ($_SESSION["kilo_rate"]/$_SESSION["cart_items_count"]);
foreach ( WC()->cart->get_cart() as $cart_item ) {
//very simplified example - every item in cart will be 100 kg
$cart_item['data']->set_weight( $each_cart_item_weight );
}
}
// print_r( $cart->get_cart_contents_weight() ); // Only for testing (not on checkout page)
}
add_action('woocommerce_cart_contents_weight', 'set_cart_contents_weight');
function set_cart_contents_weight( $weight ) {
$weight = $_SESSION["kilo_rate"];
return $weight;
}
add_action('woocommerce_cart_collaterals', 'myprefix_cart_extra_info');
function myprefix_cart_extra_info() {
echo '<div class="cart-extra-info">';
echo '<h2>Delivery Information</h2>';
echo '<p>Weight: '. $_SESSION["kilo_rate"].'Kg (Pallet plus Products)';
echo '</br> Items in Cart: '.$_SESSION["cart_items_count"];
echo '</br> Pallet Size - Length '.$_SESSION["max_length_cart"].'m Width '.$_SESSION["max_width_cart"].'m</p>';
echo '</div>';
}
//Add Warehouse Handling Fee
add_action( 'woocommerce_cart_calculate_fees','woocommerce_warehouse_picking_charge' );
function woocommerce_warehouse_picking_charge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$handling_fee = $_SESSION["cart_less_samples"] * 20;
$woocommerce->cart->add_fee( 'Warehouse Handling Fee', $handling_fee, true, '' );
}
?>
thanks for you comments, very much appreciated.
$_SESSION["kilo_rate"] come from another function that calculates the shipping weight rate based on actual volume taken up by the products loaded onto a pallet.
It does not relate to the actual weight of products in the shopping cart.
I am using weight based shipping plugin https://wordpress.org/plugins/weight-based-shipping-for-woocommerce/ which appears to calculate shipping rate using all items in cart (not the total cart weight) .
The only way I can work around this is to then change the weight of each item in the cart and that is why I divide $_SESSION["kilo_rate"] by the number or items in the cart $_SESSION["cart_items_count"]
I hope this makes sense.
I came here from this question here looking to find a solution for my WooCommerce site. I am looking for a way to get a discount in my cart only for even number of items in the cart.
For example:
If there's only 1 item in the cart: Full Price
2 Items in the cart: - (minus) 2$ for both of it
5 Items in the cart: - (minus) 2$ for 4 of it (if there's odd number of items in the cart. 1 item will always have the full price)
By the way, all of my products are having the same price.
Would someone be able to help me on this, as someone helped for the guy on the question link I've mentioned?
Here is your custom function hooked in woocommerce_cart_calculate_fees action hook, that will do what you are expecting:
add_action( 'woocommerce_cart_calculate_fees','cart_conditional_discount', 10, 1 );
function cart_conditional_discount( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_count = 0;
foreach($cart_object->get_cart() as $cart_item){
// Adds the quantity of each item to the count
$cart_count += $cart_item["quantity"];
}
// For 0 or 1 item
if( $cart_count < 2 ) {
return;
}
// More than 1
else {
// Discount calculations
$modulo = $cart_count % 2;
$discount = (-$cart_count + $modulo);
// Adding the fee
$discount_text = __('Discount', 'woocommerce');
$cart_object->add_fee( $discount_text, $discount, false );
}
}
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.