I need a way to offer shipping discount up to a maximum of $25. I'm using the Fee API to do this since there are no coupon codes for shipping. Here's my code:
add_action( 'woocommerce_cart_calculate_fees', 'conditional_shipping_discount' );
function conditional_shipping_discount() {
$max_shipping_discount = 25;
$cart_subtotal = WC()->cart->subtotal;
$current_shipping_method = WC()->session->get( 'chosen_shipping_methods' );
$current_shipping_method_cost = WC()->session->get('cart_totals')['shipping_total'];
// If our cart is > $99 AND shipping is not already free
if ( ($cart_subtotal >= 99) && ($current_shipping_method_cost > 0) ) {
// Calculate 25% of cart subtotal
$calculated_shipping_discount = $cart_subtotal * 0.25;
// $shipping_discount = lowest value
$shipping_discount = min( $current_shipping_method_cost, $calculated_shipping_discount, $max_shipping_discount );
WC()->cart->add_fee( 'Shipping Discount', -1 * abs($shipping_discount) );
}
}
This works great for the most part, except when the customer selects a different shipping method. The fee only shows the previously selected shipping discount. This GIF shows what I mean:
The fee is corrected when the page is reloaded, or when the update_checkout event is triggered by changing item quantities or updating the checkout fields.
How can I have the cart fee (shipping discount) to update immediately when the shipping method is selected? Thank you in advance.
As I am checking your function, we always got previous shipping costs if I switch/change shipping methods. there is only one issue with $current_shipping_method_cost.
So if you change 1 line
$current_shipping_method_cost = WC()->session->get('cart_totals')['shipping_total'];
to
$current_shipping_method_cost = WC()->cart->get_shipping_total();
You always getting current/active shipping costs.
full code is :
add_action( 'woocommerce_cart_calculate_fees', 'conditional_shipping_discount' );
function conditional_shipping_discount() {
$max_shipping_discount = 25;
$cart_subtotal = WC()->cart->subtotal;
//$current_shipping_method = WC()->session->get( 'chosen_shipping_methods' );
$current_shipping_method_cost = WC()->cart->get_shipping_total();
// If our cart is > $99 AND shipping is not already free
if ( ($cart_subtotal >= 99) && ($current_shipping_method_cost > 0) )
{
// Calculate 25% of cart subtotal
$calculated_shipping_discount = $cart_subtotal * 0.25;
// $shipping_discount = lowest value
$shipping_discount = min( $current_shipping_method_cost, $calculated_shipping_discount, $max_shipping_discount );
WC()->cart->add_fee( 'Shipping Discount', -1 * abs($shipping_discount) );
}
}
Related
I want to show a condictional unit price on cart line ..
if the payment method is X(bacs) (auto have added discount coupom) I have to take all %porcent discount from this coupons (multiple, sometime) and display price with and without discount and if no have coupom display normal price, I am working on this code, but I am so far to get this working ...
add_filter( 'woocommerce_cart_item_price', 'kd_custom_price_message' );
function kd_custom_price_message( $price) {
global $woocommerce, $coupon_html, $coupon, $discount_amount_html;
$applied_coupons = WC()->cart->get_applied_coupons();
$percent_coupons_only = $applied_coupons->discount_type('percent');
if ( in_array( $percent_coupons_only,$applied_coupons, true ) ) {
$total_percent_discount = $applied_coupons->get_amount();
}
}
// Get the chosen payment gateway (dynamically)
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if( $chosen_payment_method == 'bacs'){
$price_to_be_disconted = (($price / 100) * $total_percent_discount)
$discounted_price = ($price - $price_to_be_disconted);
// price with discount (I have to add CSS)
}
$card_label = '<div style="font-size:11px; color:#ada9a9; text-align:center;">3x s/ juros</div>';
// split payment 3x label
$discounted_price_label = '<div style="font-size:11px; color:green; text-align:center;">ou a vista por:</div>';
// custom sale price label for $discounted_price
return $card_label.'<div style="text-align:center;">'.$price.'</div>'.$discounted_price_label. $discounted_price ;
}
The following working code is a discount for cart with minimum 3 items not including 'sale' products Now I need to ignore categoty 'gift' (if it is in the cart) from this discount:
//10% discount at minimum 3 items in cart not for sale items
add_action('woocommerce_cart_calculate_fees' , 'custom_cart_discount', 20, 1);
function custom_cart_discount( $cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Limitations: Only when there is 5 or more non on sale items in cart
$starting_limit = 3;
// Initialising variables
$not_on_sale_subtotal = $discount = $items_count = 0;
// Iterating through each item in cart
foreach( $cart->get_cart() as $cart_item ){
// For cart items is not on sale
if( ! $cart_item['data']->is_on_sale() ){
$not_on_sale_subtotal += (float) $cart_item['line_subtotal'];
$items_count += $cart_item['quantity'];
}
}
// Discount calculation
$discount = $not_on_sale_subtotal * 0.1;
// Applied discount only cart items that are not on sale
if( $discount && $items_count >= $starting_limit )
$cart->add_fee( 'הנחת כמות 10%', -$discount );
I would recommend to work with a different approach. WooCommerce Coupons gives you a full control for what you want to achieve.
First, create a coupon in WC admin, with the 10% discount. Then, use the coupon settings to apply it on the cart or just on specific items/categories. You can see in the coupon limitations how exactly to limit the discount to specific categories (with include / exclude ), or to apply the discount only on items that are not on sale etc...
Finally, all you have to do, is just to ask or encourage the customer to apply the coupon, or automatically apply it yourself behind the scenes with:
WC()->cart->apply_coupon('YouCouponCodeGoesHere');
בהצלחה!
I have the following code that adds a Handling fee to orders with subtotal under $100. I'm trying to make a coupon that will remove the handling fee (or make it $0) that I can give to specific customers, even if their order is under $100. I've made a coupon in Woocommerce and it takes off the $25 from the cart subtotal without changing the Handling. If I don't make a coupon in Woocommerce, I get the "this coupon doesn't exist" message when I try to apply the coupon. Help?
function woo_add_cart_fee() {
global $woocommerce;
$subt = $woocommerce->cart->subtotal;
if ($subt < 100 && $coupon_code == "NOHANDLING" ) {
$handling = 0;
$woocommerce->cart->add_fee( __('Handling', 'woocommerce'), $handling );
}
elseif ($subt < 100 ) {
$handling = 25;
$woocommerce->cart->add_fee( __('Handling', 'woocommerce'), $handling );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
Thanks.
I have created a Woocommerce coupon with a discount type set to fixed cart discount and an initial coupon amount.
I want the coupon to function in such a way that when the customer enters the coupon code the total discount is computed and is set as the coupon amount. I'm using the woocommerce_applied_coupon hook in the theme's function.php.
Here's how I coded:
add_action( 'woocommerce_applied_coupon', 'action_woocommerce_applied_coupon', 10, 3 );
function action_woocommerce_applied_coupon( $array, $int, $int ){
$total_discount = 0;
$wc = wc();//use the WC class
foreach($wc->cart->get_cart() as $cart_item){
//loop through each cart line item
$total_discount += ...; //this is where the total discount is computed
}
//use the WC_COUPON class
$wc_coupon = new WC_Coupon("coupon-code");// create an instance of the class using the coupon code
$wc_coupon->set_amount($total_discount);//set coupon amount to the computed discounted price
var_dump($wc_coupon->get_amount());//check if the coupon amount did update
}
The var_dump displayed the $total_discount. But when I checked on the Cart Totals, I still see the initial coupon amount as the discount.
How do I get to update the coupon amount and apply this as the discount to the cart totals?
Try this
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupons_total_based', 10, 1 ); function auto_add_coupons_total_based( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE define your coupon code
$coupon_percent = 'xyz20'; # <=== <=== <=== <=== <=== <===
$coupon_fixed = 'fixedamount'; # <=== <=== <=== <=== <=== <=== <===
// Get cart subtotal
$subtotal = 0;
foreach($cart->get_cart() as $cart_item ){
$subtotal += $cart_item['line_subtotal'];
$subtotal += $cart_item['line_subtotal_tax']; // with taxes
}
//Set HERE the limit amount
$limit = 40; //without Tax
// Coupon type "percent" (less than 200)
if( $subtotal < 200 && ! $cart->has_discount( $coupon_percent ) ){
// If coupon "fixed amount" type is in cart we remove it
if( $cart->has_discount( $coupon_fixed ) )
$cart->remove_coupon( $coupon_fixed );
}
// Coupon type "fixed amount" (Up to 200)
if( $subtotal >= 200 && $cart->has_discount( $coupon_percent ) ) {
// If coupon "percent" type is in cart we remove it
if( $cart->has_discount( $coupon_percent ) )
$cart->remove_coupon( $coupon_percent );
// Apply the "fixed amount" type coupon code
$cart->add_discount( $coupon_fixed );
// Displaying a custom message
$message = __( "The total discount limit of $$limit has been reached", "woocommerce" );
wc_add_notice( $message, 'notice' );
}
}
I found this answer in a earlier post here (below), but I want to know of there is any way to add an extra fee based on quantity if the product quantity changes?
Lets say there is 100 items in one package. (the problem is also that there is not they same amount of item in all packages, some can be 100, some can be 150, 200, or 500)
Example:
1-99 = 1$.
100 = no fee.
101 - 199 1$
200 = no fee
201 - 299 = 1$ and so on..
Total will always be 1$ per product but the total can be more if they order several products that have these breaks. The total can be 4$ if there is 4 products with break-cost.
(Also, not sure where to put the code)
Thank you!
The code I found here: Add additional costs based on quantity in Woocommerce
// Hook before adding fees
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
/**
* Add custom fee on article specifics
* #param WC_Cart $cart
*/
function add_custom_fees( WC_Cart $cart ){
$fees = 0;
foreach( $cart->get_cart() as $item ){
// Check if odds and if it's the right item
if( $item[ 'quantity' ] % 2 == 1 && get_post_meta( $item[ 'product_id' ], 'custom_fee_for_supplier_name', true) ){
// You can also put a custom price in each produt with get_post_meta
$fees += 10;
}
}
if( $fees != 0 ){
// You can customize the descriptions here
$cart->add_fee( 'Custom fee (odds paquets)', $fees);
}
}
The woocommerce_after_cart_item_quantity_update fires right after a quantity is updated. If you modify your function a little bit (to use WC()->cart to access the cart object) you can run the same function on both hooks. I thought it might keep adding additional fees, but in my testing it seems to just recalculate the right cost for the same fee.
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
add_action( 'woocommerce_after_cart_item_quantity_update', 'add_custom_fees' );
/**
* Add custom fee on article specifics
* #param WC_Cart $cart
*/
function add_custom_fees(){
$fees = 0;
foreach( WC()->cart->get_cart() as $item ){
// Check if odds and if it's the right item
if( $item[ 'quantity' ] % 2 == 1 && get_post_meta( $item[ 'product_id' ], '_custom_fee_for_odds', true ) ){
// You can also put a custom price in each produt with get_post_meta
$fees += 10;
}
}
if( $fees > 0 ){
// You can customize the descriptions here
WC()->cart->add_fee( 'Custom fee (odds paquets)', $fees);
}
}