I found this snippet for WooCommerce to add a service fee.
// Add Service Fee to Category
function woo_add_cart_fee() {
$category_ID = '23';
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) {
// 23 is the ID of the category for which we want to remove the payment gateway
if($term->term_id == $category_ID){
$excost = 6;
}
}
$woocommerce->cart->add_fee('Service Fee', $excost, $taxable = false, $tax_class = '');
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
How can I add service fee to certain zones only?
And how can this be ignored, if cart amount is over $250
Related
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' );
someone gives me a suggestion to understand how to correctly write the shipping function in woocommerce to get this result:
a) Shipping costs are € 10 and are free for orders over € 100
b) I have two categories A and B
c) if in the cart there are products of ONLY CATEGORY B, the rule of free shipping for orders over € 100 must not be applied. So the shipping must be 10 €.
For point c) I have entered this function in function.php, but there is something wrong:
// Disable Woocommerce shipping methods based on specific category
add_filter( 'woocommerce_package_rates', 'hide_shipping_for_categories', 10, 2 );
function hide_shipping_for_categories( $rates, $package ) {
// Add your own Woocommerce categories here (either category ID, slug or name)
$terms = array( 'I nostri sottoli' );
$taxonomy = 'product_cat'; // If you need to hide shipping based on tags, then change it to product_tag
// Add shipping methods to be removed (like "local_pickup:8")
$method_instances_ids = array('free_shipping:4');
$found = false;
// Loop through cart items checking for defined product IDs
foreach( $package['contents'] as $cart_item ) {
if ( has_term( $terms, $taxonomy, $cart_item['product_id'] ) ){
$found = true;
break;
}
}
if ( ! $found ) return $rates; // If not found we exit
// Loop through your active shipping methods
foreach( $rates as $rate_id => $rate ) {
// Remove all other shipping methods other than your defined shipping method
if ( in_array( $rate_id, $method_instances_ids ) ){
unset( $rates[$rate_id] );
}
}
return $rates;
}
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' );
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.
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' );
}