How to set woocommerce order total to calculate ONLY shipping costs - php

I'm using woocommerce as a platform for booking products for delivery, People pay only for the shipping costs but not for the products.
How do I get the total amount to reflect ONLY the shipping costs and not the product prices?
I know I can set the individual product price to zero but I prefer to leave the prices there so that people can sort the items by price. Hopefully it's just a simple hack.
Thanks!

Add shipping role and assign them to all.
Or create a function that remove the product cost from the total in function.php file.
This might help:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );
function add_custom_price( $cart_object ) {
$custom_price = $shipping; // Add the shipping cost
foreach ( $cart_object->cart_contents as $key => $value ) {
$value['data']->price = $custom_price;
}
}

Related

Add additional check to a woocommerce snippet

Here's my code below which works but it's not yet fully completed. Currently it just checks if an added product in the cart has tech shipping class then apply a static $5 discount. However, what I want to achieve is to add an additional requirement.
Most of my products on my website are with NO set shipping class and the rest are set with 'tech shipping class'. I want to do the following:
The discount of $5 should only be given if the customer add one or more (it doesn't matter) of products with no shipping class assigned to them. Discount should NOT be given if there are only tech shipping class items in the cart. If there are products with no set class and tech shipping class regardless of the quantity of the items then apply a static $5 discount.
It seems unclear to me how to check if cart has other items and more specifically items with NO set class + tech shipping class then to apply that discount..
Any help is greatly appreciated. Thanks!
add_filter( 'woocommerce_package_rates', 'adjustment_in_rates_of_product_with_shipping_class', 12, 2 );
function adjustment_in_rates_of_product_with_shipping_class( $available_shipping_methods, $package ) {
// Shipping class slug to be eligible for a discount
$shipping_class = array(
'tech',
);
// Discount
$discount = 5;
// Enter the Shipping Method Value
$shipping_services = array(
'flat_rate:2',
);
$shipping_class_exists = false;
foreach(WC()->cart->get_cart_contents() as $key => $values) {
if ( in_array($values['data']->get_shipping_class() , $shipping_class) ) {
$shipping_class_exists = true;
break;
}
}
if ($shipping_class_exists) {
foreach ($available_shipping_methods as $key => $value) {
if ( in_array($value->get_id() , $shipping_services) ) {
$available_shipping_methods[$key]->cost -= $discount;
}
}
}
return $available_shipping_methods;
}
Replace this
if ( in_array($values['data']->get_shipping_class() , $shipping_class) )
For
if ( $values['data']->get_shipping_class() == '' )
I think that with this modification your code will check if there is at least one product in the cart without shipping class and in this case apply the discount.

WooCommerce update_checkout won't update shipping methods

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

Allow add to cart for specific products based on cart total in WooCommerce

In woocommerce, I am trying to find a way to only allow a product to be added a to cart only when a specific cart total amount is reached.
Example: We want to sell a bumper sticker for $1, but only if a user already has $25 worth of other products already in the cart. This is similar to Amazon's "add on" feature. However I can't find a similar WooCommerce plugin or function.
I have tried yet some code without success… Any help will be appreciated.
Can be done with a custom function hooked in woocommerce_add_to_cart_validation filter hook, where you will define:
a product Id (or multiple product Ids).
the threshold cart amount to be reached.
It will avoid for those defined products to be added to cart (displaying a custom notice) until that specific cart amount is reached.
The code:
add_filter( 'woocommerce_add_to_cart_validation', 'wc_add_on_feature', 20, 3 );
function wc_add_on_feature( $passed, $product_id, $quantity ) {
// HERE define one or many products IDs in this array
$products_ids = array( 37, 27 );
// HERE define the minimal cart amount that need to be reached
$amount_threshold = 25;
// Total amount of items in the cart after discounts
$cart_amount = WC()->cart->get_cart_contents_total();
// The condition
if( $cart_amount < $amount_threshold && in_array( $product_id, $products_ids ) ){
$passed = false;
$text_notice = __( "Cart amount need to be up to $25 in order to add this product", "woocommerce" );
wc_add_notice( $text_notice, 'error' );
}
return $passed;
}
Code goes in function.php file of your active child theme (active theme).
Tested and works.

Adding a custom cart negative fee tax issue in woocommerce

I have a shipping discount in my woocommerce site, I would like to show it on cart page and checkout page, for that I used add_fee() method.
WC()->cart->add_fee( 'Shipping Discount', -20, false );
It subtract 20 from total amount, but when I go to check order in orders inside admin it gives discount on tax too according to tax rate I configured. Is there any alternative to add discount
How can I do this in woocommerce?
For negative cart fee there is a bug related to taxes as they are applied on all tax classes even if the it's not taxable.
Now you can make a custom global cart discount This way where you will be able to define the type of discount you want, the discount amount and the source price to be discounted.
This code will display the he correct cart discounted gran total
Once submitted this discounted gran total will be passed to the order.
The code:
// Apply a discount globally on cart
add_filter( 'woocommerce_calculated_total', 'discounted_calculated_total', 10, 2 );
function discounted_calculated_total( $total, $cart ){
$amount_to_discount = $cart->cart_contents_total;
$percentage = 10; // 10% of discount
$discounted_amount = $amount_to_discount * $discount / 100;
$new_total = $total - $discounted_amount;
return round( $new_total, $cart->dp );
}
Code goes in function.php file of the active child theme (or active theme).
Tested and works.
You should need to make some additional code to display the discount amount (in cart and checkout pages and order-view) and to pass it in the order as meta data and so on…

Get Base Price in WooCommerce Bookings

I have a product in WooCommerece that has a display and base price. The following code is used:
global $woocommerce;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
$productID = $cart_item['product_id'];
break; //Take the first as an example
}
$product = new WC_Product($productID);
$base_price= $product->get_price();
$display_price = $product->get_display_price();
My issue is, the base and display price come back as the same value but they are maintained differently in the back end.
Update: Tax Settings
I understand this issue may be related to Tax settings. Here are mine:
Taxes Enabled
Prices entered inclusive of tax
Calculate tax based on shop address
Shipping tax class based on cart items
No rounding
No additional tax classes
Display prices in shop excluding tax
Display prices in cart / checkout excluding tax
No suffix
Display tax totals as itemised
There is also a blanket standard rate which is zero-rate.
And for the Product:
Taxable
Tax Class is Standard
Update
The issue stems from the fact I am using the WooCommerence Booking plugin. To get the base price of a booking:
global $woocommerce;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
$productID = $cart_item['product_id'];
break;//Take the first as an example
}
$product = new WC_Product($productID);
$admission = $product->wc_booking_cost;
$product->get_regular_price() returns the regular price.
$product->get_sale_price() returns the sale price if product is on sale.
$product->get_price() returns the price of product (sale or regular depending on what is current).
$product->get_display_price() Returns the price including or excluding tax, based on the 'woocommerce_tax_display_shop' setting.

Categories