I am trying to add some additional discounts to the cart total and I tried this code but it's not quite working for me.
function mysite_box_discount( ) {
global $woocommerce;
$total_disc = 10;
// Alter the cart discount total
$woocommerce->cart->discount_total = $total_disc;
}
add_action('woocommerce_calculate_totals', 'mysite_box_discount');
I also tried adding $cart as an argument to the function, but it didn't work.
I also tried $cart->discount_total but it is not working for me either.
Try this code
function custom_wc_add_discount() {
$total_disc = 10;
WC()->cart->add_fee( 'Discount note', -$total_disc );
}
add_action( 'woocommerce_cart_calculate_fees','custom_wc_add_discount' );
Related
On my WooCommerce site I use this function to add a 4€ fee if you select cash on delivery as payment method:
add_action('woocommerce_cart_calculate_fees', 'increase_cod_cost');
function increase_cod_cost() {
if(WC()->session->chosen_payment_method=='cod')
WC()->cart->add_fee(__('COD Fee'), 4);
}
I also use this function to immediately update the checkout whenever you change payment method so that the fee is added when you select cod, and removed when you select any other method:
add_action('woocommerce_review_order_before_payment', 'custom_checkout_update');
function custom_checkout_update() {
echo '
<script type="text/javascript">
(function($){
$(\'form.checkout\').on(\'change\', \'input[name="payment_method"]\', function() {
$(\'body\').trigger(\'update_checkout\');
});
})(jQuery);
</script>
';
}
Both functions work 100%.
Now, Instead of adding a fee, I'd like to properly increase the actual shipping cost, so I've tried this function instead of the first one:
add_filter('woocommerce_package_rates', 'increase_cod_cost_2', 10, 2);
function increase_cod_cost_2($rates, $package) {
if(WC()->session->chosen_payment_method=='cod')
$rates['flat_rate:1']->cost=$rates['flat_rate:1']->cost+4;
return $rates;
}
This function also works, but only if I empty the cart and then add a product again. For some reason it doesn't immediately update the shipping cost whenever I select cod. I really don't understand why the jQuery function would work with the first php function by adding the fee, but not with this one by changing the shipping cost. Can you please help me and tell me what's wrong? Thank you.
Please try this.
add_filter( 'woocommerce_package_rates', 'custom_shipping_costs', 20, 2 );
function custom_shipping_costs( $rates, $package ) {
// New shipping cost (can be calculated)
$new_cost = 1000;
$tax_rate = 0.4;
foreach( $rates as $rate_key => $rate ){
// Excluding free shipping methods
if( $rate->method_id != 'free_shipping'){
// Set rate cost
$rates[$rate_key]->cost = $new_cost;
// Set taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $rates[$rate_key]->taxes[$key] > 0 )
$taxes[$key] = $new_cost * $tax_rate;
}
$rates[$rate_key]->taxes = $taxes;
}
}
return $rates;
}
I cannot actually help you to fully understand what is going wrong, but I can share you some experience:
Try to include log commands in these cases, it helps you to see when the hook is called, if it is called and depending on your log details if the code went through the if clause or fell into the else case
From experience and what you write, the second hook is not always called, therefore it works when you freshly add a product but not during an shipping method change during checkout.
So I am wildly guessing you probably need another hook like
do_action( 'woocommerce_shipping_method_chosen', $chosen_method );
or something better which triggers whenever woocommerce goes to look for the available shipping methods.
Be careful that the hooks are not called sequentially and you add 4 USD more han 1 time...
PD: I've noticed that the suggested hook is not ideal neither, you could try one of these:
add_action( 'woocommerce_load_shipping_methods', 'action_woocommerce_load_shipping_methods', 10, 1 );
add_filter( 'woocommerce_package_rates', 'woocommerce_package_rates' );
or else check here all the woocommerce hooks:
https://docs.woocommerce.com/wc-apidocs/hook-docs.html
With WooCommerce, I am using WooCommerce bookings and WooCommerce force sells plugins.
I want to use WooCommerce Force Sells to add one force-sold item per number of person in a booking.
Woocommerce guys already provided a snippet to be added in functions.php which modifies the behavior of Force Sells. With this snippet you can set a fixed quantity (1) of side product to be added :
// only add one force sell item per product no matter how many of the original product are added
function my_wc_force_sell_add_to_cart_product( $product ){
$product['quantity'] = 1;
return $product;
}
add_filter( 'wc_force_sell_add_to_cart_product', 'my_wc_force_sell_add_to_cart_product' );
// when a synced force sell product is updated always set it to 1
function my_wc_force_sell_update_quantity( $quantity, $product ){
return 1;
}
add_filter( 'wc_force_sell_update_quantity', 'my_wc_force_sell_update_quantity' );
What I would like to do: Replacing the fixed quantity (1) with a function retrieving the number of people specified in the booking.
Any help would be awesome.
I think I found it !
function my_wc_force_sell_add_to_cart_product( $product ){
foreach(WC()->cart->get_cart() as $cart_item) {
// The item persons count
$person = array_sum( $cart_item['booking']['_persons'] );
}
$product['quantity'] = $person;
return $product;
}
add_filter( 'wc_force_sell_add_to_cart_product', 'my_wc_force_sell_add_to_cart_product' );
// when a synced force sell product is updated always set it to 1
function my_wc_force_sell_update_quantity( $quantity, $product ){
return 1;
}
add_filter( 'wc_force_sell_update_quantity', 'my_wc_force_sell_update_quantity' );
I've tried researching an answer for this problem now for the last 4 hours and I haven't managed to find an answer.
I have a custom fee added to my woocommerce checkout page. this is due to complicated delivery calculations which woocommerce shipping was unable to provide.
I now need to create a coupon to set this custom fee to zero if the coupon is entered.
This is setting my my custom fee
WC()->cart->add_fee( __('Shipping', 'woocommerce'), $shipping_price );
This is what I need to achieve.
if($coupon_code == "this-string"){
$shipping_price = 0;
}
I need a way to check if the coupon code submitted is equal to "this-string" and if it is I need to set $shipping Fee to zero.
Please all help will be appreciated.
You can call WC()->cart->get_applied_coupons() to get all the coupons applied to the cart. Then you can check if your coupon code is in that array. Something like this:
if(in_array($coupon_code, WC()->cart->get_applied_coupons())) {
// Do something
}
Untested, but I think you would want to do something when the code is applied, so the woocommerce_applied_coupon hook is relevant.
function so_46429329_applied_coupon( $coupon_code ) {
if( $coupon_code == "this-string" ){
$shipping_price = 0;
WC()->cart->add_fee( __('Shipping', 'woocommerce'), $shipping_price );
}
}
add_action( 'woocommerce_applied_coupon', 'so_46429329_applied_coupon' );
The part that I haven't tested is whether this overrides an existing 'Shipping Fee' or if you need to find a way to remove that first.
the below Function will add a shipping fee to your woo-commerce Cart which adds to the checkout price afterwards.
// ADD SHIPPING COST
function woo_add_cart_fee() {
WC()->cart->add_fee( __('Shipping', 'woocommerce'), 100 );
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
If you want to apply a custom coupon to the shipping fee you could do something along the lines of this
// ADD SHIPPING COST
function woo_add_cart_fee() {
$custom_coupon = $_GET["coupon_name"];
if ($custom_coupon = 'discount_code_half') {
WC()->cart->add_fee( __('Shipping', 'woocommerce'), 100 );
}elseif ($custom_coupon = 'discount_code_more_than_half') {
WC()->cart->add_fee( __('Shipping', 'woocommerce'), 50 );
}elseif ($custom_coupon = 'discount_code_free') {
WC()->cart->add_fee( __('Shipping', 'woocommerce'), 0 );
}else ( ! $custom_coupon) {
WC()->cart->add_fee( __('Shipping', 'woocommerce'), 200 );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_fee' );
For this method to work you will need to have a coupon button to submit a coupon name to the cart page.
Either from the previous page or you could just have it submit to the same page it is on. Either way your page will have to refresh so you can use the
$custom_coupon = $_GET["coupon_name"];
Hope this answer helps. :)
I have been overriding the price of products dynamically based on specific criteria, but the ajax and mini-cart doesn't seem to see the price change when the product is getting added in the cart. It shows the original price total. I can override the prices in the cart itself no problem, but you have to be on the cart or checkout page to see it. Not sure what approach to take. I felt as though I've tried everything.
Seems as though $woocommerce->cart->get_cart_total() is called to display current cart total, but it doesn't seem to run add_action( 'woocommerce_before_calculate_totals', 'woo_add_discount'); hook when called.
If you go to the actual cart page, it is the proper pricing.
This code added will display the right individual price but not the subtotal. You have to refresh the cart page by clicking on the Cart URL for it to update the $woocommerce->cart->get_cart_total() object.
I've also tried add_action( 'woocommerce_before_mini_cart', 'woo_add_discount'); which does the same thing.. you have to refresh the page after loading. I'm sure I'm not the only one who had overriden prices and can't get all the peices to fall into place.
I've tried this and see that the second comment down on the answer, someone is having the same issue but no answers.
WooCommerce: Add product to cart with price override?
Try to use apply_filters instead of add_action
I ended up fixing this myself. I tried Paul de Koning's answer. Changing to apply_filters caused the prices to go to $0. I think this is because the order they need to go in.
Here was my solution. The root cause was that I was using the change price_html function to provide the change prices for the cart. Inside that function there were add_action calls etc. Somehow, there must have been an ordering issue. This is a multi step process to ensure all areas are done correctly.
If you want to change woocommerce prices without using sessions to store the changed price for the cart while changing the display price and hiding prices, perform something like the following:
functions.php
add_action('woocommerce_get_price_html','special_price');
function special_price($price) {
//put any if statements for hiding the cart button and discounting pricing below and return true or false
$displayprice = true;
$alterprice = true;
if($displayprice === true) {
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10, 2);
add_action( 'init', 'woocommerce_add_to_cart_action', 10);
add_action( 'init', 'woocommerce_checkout_action', 10 );
} else {
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10, 2);
remove_action( 'woocommerce_before_add_to_cart_form', 'woocommerce_template_single_product_add_to_cart', 10, 2); //
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
//return blank or something like 'Signup to view price'
return '';
}
//if you are displaying the price (altered)
if($displayprice === true && $alterprice === true){
$price = price_manipulator($theid);
return $price;
//display add to cart and price
}
//if you are displaying the price (unaltered)
return $price
}
function price_manipulator($theid = '') {
if(empty($theid)){
$theid = get_the_ID();
}
$product = wc_get_product($theid);
//30% off example
$newprice = floatval($product->price * (1-0.3));
return $newprice;
}
/*version of pricing if you are adding something to cart*/
function special_price_cart($theid){
$price = price_manipulator($theid);
return $price;
}
add_action( 'woocommerce_before_calculate_totals', 'woo_add_discount');
add_action( 'woocommerce_before_mini_cart', 'woo_add_discount'); //this is if you are using the mini-cart woocommerce widget
function woo_add_discount() {
global $woocommerce;
//create if statements same as if you were displaying the price
$displayprice = true;
if($displayprice === true){
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$price = special_price_cart($cart_item['data']->id);
$price = str_replace('$','',$price);
$price = str_replace(',','',$price);
if($price > 0){
$cart_item['data']->price = floatval($price);
}
}
}
}
I need to change the price of my products in my store, with a 10% discount, if my customer is from some specific place, so, I wrote this code:
add_filter('woocommerce_price_html', 'my_price_edit');
function my_price_edit() {
$product = new WC_Product( get_the_ID() );
$price = $product->price;
echo $price * 0.9;
}
Ok, it works! But when in the checkout the price are normals without the 10% discount!
Does have some hook for change the price of the products in the checkout area or some different code to change correctly in the both (in the product page and checkout)?
New in Woocommerce too.
Your question looks really similiar to this one.
Adding Custom price with woocomerce product price in Cart & Checkout
I think you need to use the woocommerce_cart_item_subtotal hook to change the price in the cart directly (not exactly as a parameter)
I made a slightly modification to the code (changed price formula). I think that may help you.
add_filter( 'woocommerce_get_discounted_price', 'calculate_discounted_price', 10, 2 );
// Display the line total price
add_filter( 'woocommerce_cart_item_subtotal', 'display_discounted_price', 10, 2 );
function calculate_discounted_price( $price, $values ) {
// You have all your data on $values;
$price = $price*.09;
return $price;
}
// wc_price => format the price with your own currency
function display_discounted_price( $values, $item ) {
return wc_price( $item[ 'line_total' ] );
}