WooCommerce - Add handling fee based on category but not for a specific shipping method - woocommerce

I have code that works great for adding the necessary handling fees for a specific category in WooCommerce. But, I need a way to remove the fees if a customer chooses "Local Pickup" as their shipping option.
This is the code I am using for the specific category:
function df_add_handling_fee( $cart_object ) {
global $woocommerce;
$specialfeecat = 61; // category id for the special fee
$spfee = 2.95; // initialize special fee
$spfeeperprod = 0.75; //special fee per product
//Getting Cart Contents.
$cart = $woocommerce->cart->get_cart();
//Calculating Quantity
foreach($cart as $cart_val => $cid){
$qty += $cid['quantity'];
}
foreach ( $cart_object->cart_contents as $key => $value ) {
$proid = $value['product_id']; //get the product id from cart
$quantiy = $value['quantity']; //get quantity from cart
$itmprice = $value['data']->price; //get product price
$terms = get_the_terms( $proid, 'product_cat' ); //get taxonomy of the products
if ( $terms && ! is_wp_error( $terms ) ) :
foreach ( $terms as $term ) {
$catid = $term->term_id;
if($specialfeecat == $catid ) {
$spfee = $spfee + $quantiy * $spfeeperprod;
}
}
endif;
}
if($spfee > 0 ) {
$woocommerce->cart->add_fee( 'Handling Fee', $spfee, true, 'standard' );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'df_add_handling_fee' );

Related

Request - How to add Handling Fee based on Category of Product? [duplicate]

I already found this code here and it works for like 80/90% for me (see below).
This code adds 60 euro to my cart when there is a product from category ID 349 in the cart. When I add a product from that category to my cart when the cart is empty it works fine. But when there is already a product in my cart from a different category and then I add the product with category 349 it doesn't add the 60 euro extra fee. How is this possible?
function woo_add_cart_fee() {
$category_ID = '349';
global $woocommerce;
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
// Get the terms, i.e. category list using the ID of the product
$terms = get_the_terms( $values['product_id'], 'product_cat' );
// Because a product can have multiple categories, we need to iterate through the list of the products category for a match
foreach ($terms as $term) {
// 349 is the ID of the category for which we want to remove the payment gateway
if($term->term_id == $category_ID){
$excost = 60;
}
}
$woocommerce->cart->add_fee('Extra bezorgkosten kunstgras', $excost, $taxable = false, $tax_class = '');
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
The code you are using is a bit outdated and you should use has_term() Wordpress conditional function to target a product category this way:
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('349');
$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 = 60;
}
// Adding the fee
if ( $fee_amount > 0 ){
// Last argument is related to enable tax (true or false)
WC()->cart->add_fee( __( "Extra bezorgkosten kunstgras", "woocommerce" ), $fee_amount, false );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
A fee of 60 will always be added if there is in cart an item from 349 product category ID.
I found a solution like the following. Note that I kept adding a fee, because I started from a previous snippet. You can apply an existing discount or calculate a different total according to your needs.
In this case, I apply a negative fee - like a discount - according to a >= 300 total value of the cart, whose values would be -25% only for local_pickup shipping method, calculating taxes in addition.
function discount_to_cat(){
// thanks to LoicTheAztec's snippet
$cat_in_cart = false;
// Loop through all products in the Cart
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( has_term( 'category_to_pick', 'product_cat', $cart_item['product_id'] ) ) {
$cat_in_cart = true;
$tot_category_price = $cart_item['data']->get_price();
$tot_category_qty = $cart_item['quantity'];
$tot_category = $tot_category_price * $tot_category_qty;
break;
}
} global $product;
$total = WC()->cart->subtotal;
$discount_label = "";
if($total >= 300){
$discount_label=15;
}
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = explode(':',$chosen_methods[0]);
if($chosen_shipping[0]=='local_pickup'){
$discount_label=25;
}
$discount_applied = ($total-$tot_category)*$discount_label/100;
if($discount_label!=""){
$discount_applied_net = ($discount_applied/1.1); //1.1 according taxes for shipping
WC()->cart->add_fee( "Discount applied: ($discount_label%)", -$discount_applied_net, false );
}
}
add_action( 'woocommerce_cart_calculate_fees','discount_to_cat' );

wooocmmerce cart loop price not working, remove comma last [duplicate]

I am trying to send the woocommerce cart items to third party shipping tool. I need the item name, quantity and individual price to be sent to the third party. How can this be achieved?
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = $values['data']->post;
echo $_product->post_title;
}
How do I get item name and quantity and price?
Try this :
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = wc_get_product( $values['data']->get_id());
echo "<b>".$_product->get_title().'</b> <br> Quantity: '.$values['quantity'].'<br>';
$price = get_post_meta($values['product_id'] , '_price', true);
echo " Price: ".$price."<br>";
}
?>
To get Product Image and Regular & Sale Price:
<?php
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = wc_get_product( $values['data']->get_id() );
//product image
$getProductDetail = wc_get_product( $values['product_id'] );
echo $getProductDetail->get_image(); // accepts 2 arguments ( size, attr )
echo "<b>".$_product->get_title() .'</b> <br> Quantity: '.$values['quantity'].'<br>';
$price = get_post_meta($values['product_id'] , '_price', true);
echo " Price: ".$price."<br>";
/*Regular Price and Sale Price*/
echo "Regular Price: ".get_post_meta($values['product_id'] , '_regular_price', true)."<br>";
echo "Sale Price: ".get_post_meta($values['product_id'] , '_sale_price', true)."<br>";
}
?>
Since WooCommerce 2.1 (2014) you should use the WC function instead of the global. You can also call more appropriate functions:
foreach ( WC()->cart->get_cart() as $cart_item ) {
$item_name = $cart_item['data']->get_title();
$quantity = $cart_item['quantity'];
$price = $cart_item['data']->get_price();
...
This will not only be clean code, but it will be better than accessing the post_meta directly because it will apply filters if necessary.
Note on product price
The price of the cart item may be different from that of the
product (stored in the database as post meta).
Some plugins or custom functions (added to the functions.php of the active theme) can change the price of the cart item.
If you want to be sure you get the price of the product added to the cart you will have to get it like this:
foreach ( WC()->cart->get_cart() as $cart_item ) {
// gets the cart item quantity
$quantity = $cart_item['quantity'];
// gets the cart item subtotal
$line_subtotal = $cart_item['line_subtotal'];
$line_subtotal_tax = $cart_item['line_subtotal_tax'];
// gets the cart item total
$line_total = $cart_item['line_total'];
$line_tax = $cart_item['line_tax'];
// unit price of the product
$item_price = $line_subtotal / $quantity;
$item_tax = $line_subtotal_tax / $quantity;
}
Instead of:
foreach ( WC()->cart->get_cart() as $cart_item ) {
// gets the product object
$product = $cart_item['data'];
// gets the product prices
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
$price = $product->get_price();
}
Other data you can get:
foreach ( WC()->cart->get_cart() as $cart_item ) {
// get the data of the cart item
$product_id = $cart_item['product_id'];
$variation_id = $cart_item['variation_id'];
// gets the cart item quantity
$quantity = $cart_item['quantity'];
// gets the cart item subtotal
$line_subtotal = $cart_item['line_subtotal'];
$line_subtotal_tax = $cart_item['line_subtotal_tax'];
// gets the cart item total
$line_total = $cart_item['line_total'];
$line_tax = $cart_item['line_tax'];
// unit price of the product
$item_price = $line_subtotal / $quantity;
$item_tax = $line_subtotal_tax / $quantity;
// gets the product object
$product = $cart_item['data'];
// get the data of the product
$sku = $product->get_sku();
$name = $product->get_name();
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
$price = $product->get_price();
$stock_qty = $product->get_stock_quantity();
// attributes
$attributes = $product->get_attributes();
$attribute = $product->get_attribute( 'pa_attribute-name' ); // // specific attribute eg. "pa_color"
// custom meta
$custom_meta = $product->get_meta( '_custom_meta_key', true );
// product categories
$categories = wc_get_product_category_list( $product->get_id() ); // returns a string with all product categories separated by a comma
}
This will show only Cart Items Count.
global $woocommerce;
echo $woocommerce->cart->cart_contents_count;
you can get the product name like this
foreach ( $cart_object->cart_contents as $value ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $value['data'] );
if ( ! $_product->is_visible() ) {
echo $_product->get_title();
} else {
echo $_product->get_title();
}
}
Most of the time you want to get the IDs of the products in the cart so that you can make some comparison with some other logic - example settings in the backend.
In such a case you can extend the answer from #Rohil_PHPBeginner and return the IDs in an array as follows :
<?php
function njengah_get_ids_of_products_in_cart(){
global $woocommerce;
$productsInCart = array();
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values) {
$_product = wc_get_product( $values['data']->get_id());
/* Display Cart Items Content */
echo "<b>".$_product->get_title().'</b> <br> Quantity: '.$values['quantity'].'<br>';
$price = get_post_meta($values['product_id'] , '_price', true);
echo " Price: ".$price."<br>";
/**Get IDs and in put them in an Array**/
$productsInCart_Ids[] = $_product->get_id();
}
/** To Display **/
print_r($productsInCart_Ids);
/**To Return for Comparision with some Other Logic**/
return $productsInCart_Ids;
}

Remove checkout fields for a defined product category in Woocommerce

In woocommerce I am trying to remove unwanted checkout shipping fields for a product category "house".
Here is my code:
function woo_custom_category_is_in_the_cart( $categories ) {
// Products currently in the cart
$cart_ids = array();
// Categories currently in the cart
$cart_categories = array('house');
// Find each product in the cart and add it to the $cart_ids array
foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
$cart_product = $values['data'];
$cart_ids[] = $cart_product->id;
}
// Connect the products in the cart w/ their categories
foreach( $cart_ids as $id ) {
$products_categories = get_the_terms( $id, 'product_cat' );
// Loop through each product category and add it to our $cart_categories array
foreach ( $products_categories as $products_category ) {
$cart_categories[] = $products_category->slug;
}
}
// If one of the special categories are in the cart, return true.
if ( ! empty( array_intersect( $categories, $cart_categories ) ) ) {
return true;
} else {
return false;
}
}
/************************************************
* Remove unwanted checkout fields on condition *
************************************************/
function woo_custom_remove_checkout_field( $fields ) {
$categories = array( 'house' );
// If a special category is in the cart, hide the following billing fields
if ( woo_custom_category_is_in_the_cart( $categories ) ) {
// hide the billing fields
unset($fields['shipping']['shipping_first_name']);
unset($fields['shipping']['shipping_last_name']);
unset($fields['shipping']['shipping_company']);
unset($fields['shipping']['shipping_address_1']);
unset($fields['shipping']['shipping_address_2']);
unset($fields['shipping']['shipping_city']);
unset($fields['shipping']['shipping_postcode']);
unset($fields['shipping']['shipping_country']);
unset($fields['shipping']['shipping_state']);
unset($fields['shipping']['shipping_phone']);
// hide the additional information section
add_filter('woocommerce_enable_order_notes_field', '__return_false');
add_filter( 'woocommerce_ship_to_different_address_checked', '__return_false' );
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields' , 'woo_custom_remove_checkout_field' );
But the code removes the fields on for other product categories too…
What I am doing wrong?
Any help is appreciated.
I have revisited and simplified your code:
add_filter( 'woocommerce_checkout_fields', 'conditionally_remove_checkout_fields', 25, 1 );
function conditionally_remove_checkout_fields( $fields ) {
// HERE the defined product Categories
$categories = array('house');
$found = false;
// CHECK CART ITEMS: search for items from our defined product category
foreach ( WC()->cart->get_cart() as $cart_item ){
if( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ) {
$found = true;
break;
}
}
// If a special category is in the cart, remove some shipping fields
if ( $found ) {
// hide the billing fields
unset($fields['shipping']['shipping_first_name']);
unset($fields['shipping']['shipping_last_name']);
unset($fields['shipping']['shipping_company']);
unset($fields['shipping']['shipping_address_1']);
unset($fields['shipping']['shipping_address_2']);
unset($fields['shipping']['shipping_city']);
unset($fields['shipping']['shipping_postcode']);
unset($fields['shipping']['shipping_country']);
unset($fields['shipping']['shipping_state']);
unset($fields['shipping']['shipping_phone']);
// hide the additional information section
add_filter('woocommerce_enable_order_notes_field', '__return_false');
add_filter( 'woocommerce_ship_to_different_address_checked', '__return_false' );
}
return $fields;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

how to remove a product or category from cart count?

I would like to know, in Wordpress + WooCommerce: How to remove a specific product or category from the cart count ?
I'm selling a product associated with a second product (which is a subscription) , and when I add 5 of this product to the Basket, the Mini Cart in the header shows 10 products.
This can be scary for the customers. I took a look at the similar questions, but it didn't work for the Cart in the header.
You can filter the cart quantity via woocommerce_cart_contents_count. Change slug_of_category_to_ignore to suit.
/**
* Filters the reported number of cart items.
* Counts only items NOT in certain category.
*
* #param int $count
* #return int
*/
function so_43498002_cart_contents_count( $count ) {
$cart_items = WC()->cart->get_cart();
$subtract = 0;
foreach ( $cart_items as $key => $value ) {
if ( has_term( 'slug_of_category_to_ignore', 'product_cat', $value['product_id'] ) ) {
$count -= $value[ 'quantity' ];
}
}
return $count;
}
add_filter( 'woocommerce_cart_contents_count', 'so_43498002_cart_contents_count' );
Try This
add_action( 'woocommerce_check_cart_items', 'woocommerce_check_cart_quantities' );
function woocommerce_check_cart_quantities() {
$total_products = WC()->cart->cart_contents_count;
$multiples = 6;
$totale = 0;
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$prodotti = $values['data'];
if( ! has_term( array( 169, 152 ), 'product_cat', $prodotti->id ) ){
$totale += $values['quantity'];
}
}
echo $totale;
if ( ( $totale % $multiples ) > 0 ){
wc_add_notice( sprintf( __('You need to buy in multiples of %d products', 'your-textdomain'), $multiples ), 'error' );
}
}

Add a fee to WooCommerce per product, based on category and add to sales tax

I have seen several posts relating to adding a service fee to a WooCommerce item based on Category. Tickets in my case. I have had success with several of the codes presented. However In all cases Sales Tax was not applied to the new sub total. I'm stuck trying to make that happen. So with the code below I am not taxing the up charge resulting in under collection of taxes.
Here is the code I'm currently using:
/* Service fee for tickets */
function df_add_ticket_surcharge( $cart_object ) {
global $woocommerce;
$specialfeecat = 23; // category id for the special fee
$spfee = 0.00; // initialize special fee
$spfeeperprod = 0.214; //special fee per product
foreach ( $cart_object->cart_contents as $key => $value ) {
$proid = $value['product_id']; //get the product id from cart
$quantiy = $value['quantity']; //get quantity from cart
$itmprice = $value['data']->price; //get product price
$terms = get_the_terms( $proid, 'product_cat' ); //get taxonamy of the prducts
if ( $terms && ! is_wp_error( $terms ) ) :
foreach ( $terms as $term ) {
$catid = $term->term_id;
if($specialfeecat == $catid ) {
$spfee = $spfee + $itmprice * $quantiy * $spfeeperprod;
}
}
endif;
}
if($spfee > 0 ) {
$woocommerce->cart->add_fee( 'Service Fee', $spfee, true, $taxable = true, $tax_class = 'standard' );
}

Resources