This script is adding a fee if the product is in a particular category.
The script is working but only for one cart item.
But if there are 2 or more items it wil not multiply in the cart.
What am I doing wrong?
add_action( 'woocommerce_cart_calculate_fees','custom_pcat_fee', 20, 1 );
function custom_pcat_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// iPhone CAT
$iphone_categories = array('74');
$iphone_fee_amount = 0;
// iPad CAT
$ipad_categories = array('75');
$ipad_fee_amount = 0;
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ){
$quantiy = $cart_item['quantity']; //get quantity from cart
if( has_term( $iphone_categories, 'product_cat', $cart_item['product_id']) )
$iphone_fee_amount = 4.70 * $quantiy;
if( has_term( $ipad_categories, 'product_cat', $cart_item['product_id']) )
$ipad_fee_amount = 2.60 * $quantiy;
}
// Adding the fee for iPhone
if ( $iphone_fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Thuiskopieheffing iPhone", "woocommerce" ), $iphone_fee_amount, true );
}
// Adding the fee for iPad
if ( $ipad_fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Thuiskopieheffing iPad", "woocommerce" ), $ipad_fee_amount, true );
}
}```
I think you missing basic summation in foreach. you override $iphone_fee_amount and $ipad_fee_amount you have to append each value to that variable. check the code below.
function custom_pcat_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// iPhone CAT
$iphone_categories = array('74');
$iphone_fee_amount = 0;
// iPad CAT
$ipad_categories = array('75');
$ipad_fee_amount = 0;
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ){
$quantiy = $cart_item['quantity']; //get quantity from cart
if( has_term( $iphone_categories, 'product_cat', $cart_item['product_id']) )
$iphone_fee_amount = $iphone_fee_amount + ( 4.70 * $quantiy );
if( has_term( $ipad_categories, 'product_cat', $cart_item['product_id']) )
$ipad_fee_amount = $iphone_fee_amount + ( 2.60 * $quantiy );
}
// Adding the fee for iPhone
if ( $iphone_fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Thuiskopieheffing iPhone", "woocommerce" ), $iphone_fee_amount, true );
}
// Adding the fee for iPad
if ( $ipad_fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Thuiskopieheffing iPad", "woocommerce" ), $ipad_fee_amount, true );
}
}
Related
I am trying to get some code to work but I am having issues with site errors.
The code is designed to add a cart fee for each set category in the cart, this is applied just once per category. I then added a second part where if a fee exists, the base rate shipping (I only have one shipping method) should be adjusted to be free shipping.
add_action( 'woocommerce_cart_calculate_fees', 'custom_pcat_fee', 20, 1 );
function custom_pcat_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Set HERE your categories (can be term IDs, slugs or names) in a coma separated array
$categories = array('512', '347');
$fee_amount = 0;
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ){
if( has_term( $categories, 'product_cat', $cart_item['product_id']) )
$fee_amount += 12.50;
}
// Adding the fee
if ( $fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Shipping Surcharge", "woocommerce" ), $fee_amount, true );
// Apply free shipping
$rates = WC()->shipping->get_package_rates( WC()->cart->get_shipping_packages()[0] );
foreach ( $rates as $rate ) {
if ( $rate->id == 'free_shipping' ) {
$rate->cost = 0;
$rate->label = __( "Adjusted Base Rate Shipping", "woocommerce" );
break;
}
}
}
}
I am trying to make custom checkout fees if there is more items in cart than 5 or 10, but I also have to exclude categories "tickets" and "vouchers" from count. I found good code examples but none with a negative category selection and I really don't want to set the rules manually for all my 20+ categories like in this post, it would be best to apply it for all EXCEPT an array of 2 categories.
Here is my code that doesn't work:
add_action( 'woocommerce_cart_calculate_fees','woocommerce_cart_extra_cost', 10, 1 );
function woocommerce_cart_extra_cost( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
// Below your category term ids, slugs or names to be excluded
$excluded_terms = array('tickets', 'vouchers');
$cart_item_count = 0; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
// Excluding some product category from the count
if ( ! has_term( $excluded_terms, 'product_cat', $item['product_id'] ) ) {
$items_count += $item['quantity'];
}
}
// CONDITIONAL ITEMS QUANTITY FEE AMOUNT
if( $cart_item_count < 6 )
$fee = 0;
elseif( $cart_item_count >= 6 && $cart_item_count < 11 )
$fee = 3;
elseif( $cart_item_count >= 11 )
$fee = 5;
if( $fee > 0 )
$cart->add_fee( __( "Handling Fee", "woocommerce" ), $fee, true);
}
What's wrong with it?
Any code corrections will be greatly appreciated. Thank you.
Edit: I ended up using this answer: WooCommerce Quick cart fee
Can you please try below code, I have revised your code little bit:
add_action( 'woocommerce_cart_calculate_fees','woocommerce_cart_extra_cost', 10, 1 );
function woocommerce_cart_extra_cost( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
// Below your category term ids, slugs or names to be excluded
$excluded_terms = array('tickets', 'vouchers');
$fee = 0;
$cart_item_count = count( WC()->cart->get_cart() ); // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
// Excluding some product category from the count
if ( has_term( $excluded_terms, 'product_cat', $item['product_id'] ) ) {
$cart_item_count = $cart_item_count - 1;
}
}
// CONDITIONAL ITEMS QUANTITY FEE AMOUNT
if( $cart_item_count < 2 )
$fee = 6;
elseif( $cart_item_count >= 6 && $cart_item_count < 11 )
$fee = 3;
elseif( $cart_item_count >= 11 )
$fee = 5;
if( $fee > 0 )
$cart->add_fee( __( "Handling Fee", "woocommerce" ), $fee, true);
}
I want to add a fee for a category (A), but to be calculated only when in the order are products from other categories (B, C, D, etc).
But if only category A products are ordered, that tax does not apply.
In my code the fee is added in both situations. Can you guide me for a better solution?
I add this code on my site:
add_action( 'woocommerce_cart_calculate_fees','custom_pcat_fee', 20, 1 );
function custom_pcat_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Set HERE your categories (can be term IDs, slugs or names) in a coma separated array
$categories = array('396');
$fee_amount = 0;
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ){
if( has_term( $categories, 'product_cat', $cart_item['product_id']) )
$fee_amount = 20;
}
// Adding the fee
if ( $fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Taxa livrare ROPET", "woocommerce" ), $fee_amount, false );
}
}
You can use wp_get_post_terms() to retrieves the terms for a post. When going through the cart contents we collect the term ids,
which we can then compare to see if there is a match.
WordPress functions used:
wp_get_post_terms() - Retrieves the terms for a post
PHP functions used:
in_array() - Checks if a value exists in an array
array_intersect() - Computes the intersection of arrays
So you get:
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Only use term IDs
$category_a = 15;
$other_categories = array( 16, 17, 18 );
// Fee amount
$fee_amount = 20;
// Initialize
$term_ids = array();
// Loop through cart contents
foreach ( $cart->get_cart_contents() as $cart_item ) {
// Get product id
$product_id = $cart_item['product_id'];
// Retrieves the terms for a post.
$terms = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
// Loop through
foreach ( $terms as $term_id ) {
// Checks if a value NOT exists in an array
if ( ! in_array( $term_id, $term_ids ) ) {
// Push
$term_ids[] = $term_id;
}
}
}
// Check for a specific category (A)
if ( in_array( $category_a, $term_ids ) ) {
// Check if ANY of the term ids exist
if ( ! empty ( array_intersect( $other_categories, $term_ids ) ) ) {
// Last argument is related to enable tax (true or false)
$cart->add_fee( __( 'Taxa livrare ROPET', 'woocommerce' ), $fee_amount, false );
}
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
I'm trying to add dynamic discount to all products who have the tag: "bulk-discount" I want the discount to happen if a customer buys eg. 5 similar or different prducts with the tag.
I'm working with this code. And this answer.
This is what i have:
add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );
function bbloomer_quantity_based_pricing( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get an instance of the WC_Product object
$product = $cart_item['data'];
// Get product id
$product_id = $cart_item['product_id'];
if( method_exists( $product, 'set_name' ) && has_term( 'bulk-discount', 'product_tag', $product_id ) ) {
// Define discount rules and thresholds
$threshold1 = 5; // Change price if items > 4
$discount1 = 0.05; // Reduce unit price by 5%
$threshold2 = 10; // Change price if items > 9
$discount2 = 0.1; // Reduce unit price by 10%
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] < $threshold2 ) {
$price = round( $cart_item['data']->get_price() * ( 1 - $discount1 ), 2 );
$cart_item['data']->set_price( $price );
} elseif ( $cart_item['quantity'] >= $threshold2 ) {
$price = round( $cart_item['data']->get_price() * ( 1 - $discount2 ), 2 );
$cart_item['data']->set_price( $price );
}
}
}
The first loop counts how many times the tag appears on a single product or multiple items from the same product
The 2nd loop applies the discount if the condition is met
function bbloomer_quantity_based_pricing( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// count tag found
$tag_found = 0;
// Loop through cart items, count how many times tag occurs
foreach ( $cart->get_cart() as $cart_item ) {
// Get an instance of the WC_Product object
$product = $cart_item['data'];
// Get product id
$product_id = $cart_item['product_id'];
// if product has tag
if( has_term( 'bulk-discount', 'product_tag', $product_id ) ) {
// Get quantity from product in cart
$quantity = $cart_item['quantity'];
// if product quantity > 1
if ( $quantity > 1) {
$tag_found = $tag_found + $quantity;
} else {
$tag_found += 1;
}
}
}
// Define discount rules and thresholds
$threshold = 5; // Change price if items > 4
$discount = 0.05; // Reduce unit price by 5%
// if tag found >= $threshold
if ( $tag_found >= $threshold ) {
// Loop through cart items, add discount
foreach ( $cart->get_cart() as $cart_item ) {
// Get an instance of the WC_Product object
$product = $cart_item['data'];
// Get product id
$product_id = $cart_item['product_id'];
// if product has tag
if( has_term( 'bulk-discount', 'product_tag', $product_id ) ) {
// calculate new price
$price = round( $cart_item['data']->get_price() * ( 1 - $discount ), 2 );
// set new price
$cart_item['data']->set_price( $price );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 10, 1 );
Related: Multiple bulk dynamic pricing for WooCommerce products with specific product-tag
I want implement functionality on my site when user buy a x product then user will get a y product as free.
In my site i have variable products.If customer buy 1kg pack of X product then customer want to get Free 30ml of Y product.
I added below code in my function.php but its working the problem is when refreshing the page gift product count is increasing.
my updated code.
add_action( 'woocommerce_before_cart', 'bbloomer_apply_matched_coupons' );
function bbloomer_apply_matched_coupons() {
global $woocommerce;
$cat_in_cart = false;
foreach ( $woocommerce->cart->cart_contents as $key => $values ) {
// this is your product ID
$autocoupon = array( 123411 );
if( in_array( $values['variation_id'], $autocoupon ) ) {
$cat_in_cart = true;
break;
}
}
if ( $cat_in_cart ) {
$product_id = 2044;
$quantity = 1;
$variation_id = 2046;
$variation = array(
'pa_size' => '30ml'
);
$woocommerce->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation );
}
}
Add this to start of 'functions.php'.
ob_start();
session_start();
Then add this code.
add_action( 'woocommerce_before_cart', 'bbloomer_apply_matched_coupons' );
function bbloomer_apply_matched_coupons() {
if(!$_SESSION['GiftAdded']) {
global $woocommerce;
$cat_in_cart = false;
$coupon_in_cart = false;
$autocoupon = array( 123411 ); // variation ids of products that offers gifts
$freecoupon = array( 2046 ); // variation ids of products that are gift coupons
foreach ( $woocommerce->cart->cart_contents as $key => $values ) {
if( in_array( $values['variation_id'], $autocoupon ) ) {
$cat_in_cart = true;
}
if( in_array( $values['variation_id'], $freecoupon) ) {
$coupon_in_cart = true;
}
}
if ( $cat_in_cart && !$coupon_in_cart ) {
$product_id = 2044;
$quantity = 1;
$variation_id = 2046;
$variation = array( 'pa_size' => '30ml' );
$woocommerce->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation );
$_SESSION['GiftAdded']=true;
}
}
}
The $_SESSION['GiftAdded'] will prevent the gift product added again when its deleted manually.
There is an other alternative based on quantity using another hook… It handles when quantities are changed or products removed from cart and set the price of the free product to zero:
add_action( 'woocommerce_before_calculate_totals', 'add_free_product_to_cart', 20, 1 );
function add_free_product_to_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$products_ids = array( 123411 ); // Products IDs to check
$free_var_id = 2046; // free product (variation ID)
$free_prod_id = 2044; // free product (product ID)
$free_attr = array( 'pa_size' => 'medium' ); // Free product attribute
$free_price = 0;
$targeted = $free = array('qty' => 0 ); // Initializing
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( in_array( $cart_item['data']->get_id(), $products_ids ) ) {
$targeted['qty'] += $cart_item['quantity'];
} elseif ( $cart_item['data']->get_id() == $free_var_id ) {
$cart_item['data']->set_price($free_price);
$free['qty'] += $cart_item['quantity'];
$free['key'] = $cart_item_key;
}
}
// We exit (No changes are needed)
if( $targeted['qty'] == $free['qty'] )
return;
if( $targeted['qty'] > 0 && $free['qty'] == 0 )
{
// Add the free product
$cart->add_to_cart( $free_prod_id, $targeted['qty'], $free_var_id, $free_attr );
}
elseif( $targeted['qty'] > 0 && $free['qty'] > 0 && $targeted['qty'] != $free['qty'] )
{
// Adjust free product quantity
$cart->set_quantity( $free['key'], $targeted['qty'] );
}
elseif( $targeted['qty'] == 0 && $free['qty'] > 0)
{
// Remove free product
$cart->remove_cart_item( $free['key'] );
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.