It's easy to find how to hide other shipping methods when free shipping is available. But I would like to hide other shipping methods when flat rate is available (I have custom other methods).
Can you help please ?
regards
The code below is modified from this article :
add_filter('woocommerce_package_rates', 'xa_hide_shipping_rates_when_flat_rate_is_available', 10, 2);
function xa_hide_shipping_rates_when_flat_rate_is_available($rates, $package) {
global $woocommerce;
$version = "2.6";
if (version_compare($woocommerce->version, $version, ">=")) {
foreach($rates as $key => $value) {
$key_part = explode(":", $key);
$method_title = $key_part[0];
if ('flat_rate' == $method_title) {
$flat_rate_shipping = $rates[$key];
// Unset all rates.
$rates = array();
// Restore flat rate shipping rate.
$rates[$key] = $flat_rate_shipping;
return $rates;
}
}
}
else {
if (isset($rates['flat_rate'])) {
// Below code is for unsetting single shipping method/option.
$flat_rate = $rates['flat_rate'];
// Unset all rates.
$rates = array();
// Restore flat rate shipping rate.
$rates['flat_rate'] = $flat_rate;
}
}
return $rates;
}
I am not sure which WooCommerce version you are using but I have tested for version 2.6 but not the versions before it.
Related
i have a small problem. In my project a few months ago i used add_filter to filtering payments methods based on shipping. I have shipping methods for cash on delivery packages so I hide online payments methods if customer select one of this methods. My code:
add_filter('woocommerce_available_payment_gateways','gateway_disable_for_shipping_rate', 10);
function gateway_disable_for_shipping_rate($available_gateways)
{
if (!is_admin()) {
$chosen_methods = WC()->session->get('chosen_shipping_methods');
$chosen_shipping = $chosen_methods[0];
// some conditionals...
}
return $available_gateways;
}
Today i must add fees based on payment method. I realize that with this code:
add_action('woocommerce_cart_calculate_fees', 'add_checkout_fee_for_gateway', 10);
function add_checkout_fee_for_gateway()
{
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
$cart = WC()->cart;
// RESET
$cart->fees_api()->set_fees([]);
// END RESET
$chosen_gateway = WC()->session->get('chosen_payment_method');
if ($chosen_gateway === 'paypal') {
$tax = $cart->subtotal * 0.05;
$cart->add_fee('PayPal', $tax);
} else if ($chosen_gateway === 'eh_stripe_pay') {
$tax = $cart->subtotal * 0.02;
$cart->add_fee('Stripe', $tax);
} else if ($chosen_gateway === 'cod') {
$tax = $cart->subtotal * 0.02;
$cart->add_fee('COD', $tax);
}
}
add_action('wp_footer', 'refresh_checkout_on_payment_methods_change');
function refresh_checkout_on_payment_methods_change()
{
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) )
return;
?>
<script type="text/javascript">
(function($){
$('form.checkout').on('change', 'input[name^=\'payment_method\']', function(){
$(document.body).trigger('update_checkout');
});
$('form.checkout').on('change', 'input[name^=\'shipping_method\']', function(){
$(document.body).trigger('update_checkout');
});
})(jQuery);
</script>
<?php
}
And problem is with fee. Scenario:
I change shipping method. Shipping method has payment via paypal. I check this and fee is added to total price -> good.
Now i change shipping method. Now shipping method has only payment via cod. My fee is not update.
My fee updates only if i can click to payment method, if i cant click - not update.
I log this and i think actions to calculate fee run first, before run filtering.
So i have 'checked method' and calculate fee, but after run filter this method is disabled but calculates for fee are already saved. If i change methods many times always calculate fee based on previous method, not current checked.
Small example:
https://vimeo.com/720301741
foreach( $cart as $cart_item_id => $citem ) {
if ( $citem['product_id'] == $gift ) {
$item_id = $cart_item_id;
$grp = $citem['data']->get_regular_price();
//$woocommerce->cart->cart_contents[$cart_item_id]['line_subtotal'] = 1;
$woocommerce->cart->line_subtotal($cart_item_id, '0');
$woocommerce->cart->cart_contents[$cart_item_id]['line_subtotal'] = 1;
//WC()->cart->set_session();
//$woocommerce->cart->set_session();
}
}
I can get access to cart details in "woocommerce_before_calculate_totals" hook.
But I can not manage to change the line_subtotal of a specific product.
Is there any way to do it using "woocommerce_before_calculate_totals" hook?
Thanks in advance.
There is a way doing this using woocommerce_before_calculate_totals, but as you do that it would also affect the individual price of the product.
So if you choose to do this, you would have to reset the individual price of the product by then filtering woocommerce_cart_item_price.
But this is kind of wierd so I would try using woocommerce_cart_item_subtotal, if it works in your usecase.
add_filter('woocommerce_cart_item_subtotal','new_cart_item_subtotal_filter', 10, 3);
function new_cart_item_subtotal_filter( $oldTotal, $cart_item, $cart_item_key){
//filter...
return $oldTotal;
}
I've been looking over Stack for an answer but can't find one (even when reading this and this)
Here my trouble: i would like to display (or at least get the variable) of the default and selected price of a woocommerce variable product.
System: Wordpress 5,6 + woocommerce
With a single product, my code is working well and i obtain a display like this:
Display for a single product with weight and price rewritten on right after quantity selector
And code is the following:
global $woocommerce;
$productxyz = new WC_Product( get_the_ID() );
$priceproduct = $productxyz->get_regular_price();
$poidsproduct = $productxyz->get_weight();
// CODE FOR THE + AND - QUANTITY
var $ = jQuery;
$(document).ready(function(){
$('.decrement').click(function () {
$moninput = $(this).nextAll('input#Qte');
if( Number($moninput.val()) > $moninput.attr("min") ){
$moninput.val(Number($moninput.val()) - 1);
}else{
$moninput.val($moninput.attr("min"));
}
Update_Price();
event.preventDefault();
})
$('.increment').click(function () {
$moninput = $(this).nextAll('input#Qte');
$moninput.val(Number($moninput.val()) + 1);
Update_Price();
event.preventDefault();
})
$('#btn-cady').click(function () {
$('[name="add-to-cart"]').click();
event.preventDefault();
})
// CODE FOR THE TEXT DISPLAYED ON THE RIGHT OF THE QUANTITY SELECTOR
function Update_Price(){
if($('input#Qte').attr('price') > 0){
$total = parseFloat($('input#Qte').val()) * $('input#Qte').attr('price');
$qtyactuelle = parseFloat($('input#Qte').val());
$('input[name="quantity"]').val($('input#Qte').val());
console.log($total);
if( $qtyactuelle < 2){
$('.Qtotal h4').html("<font color='#401816'>pack soit " +($('input#Qte').attr('weight')*parseFloat($('input#Qte').val()))+"g |</font> "+parseFloat($total).toFixed(2)+" €");
}
if($qtyactuelle > 1){
$('.Qtotal h4').html("<font color='#401816'>packs soit " +($('input#Qte').attr('weight')*parseFloat($('input#Qte').val()))+"g |</font> "+parseFloat($total).toFixed(2)+" €");
}
}
}
Update_Price();
});
But for a variation product... i feel so ashamed to show my result because when it's displaying well, function is not working. And when functions are working, display is very terrible
Code result for variation product
I tried to use get_available_variations() and also the following foreach but...
foreach( $product->get_available_variations() as $variation ){
$found = true;
// Loop through variation attributes
foreach( $variation['attributes'] as $key => $value ){
$taxonomy = str_replace( 'attribute_', '', $key );
// Searching for a matching variation as default
if( isset($default_attributes[$taxonomy]) && $default_attributes[$taxonomy] != $value ){
$found = false;
break;
}
}
// If we get the default variation
if( $found ) {
$default_variaton = $variation;
break;
}
Has anyone an idea of how to developp it? I'm feeling speechless.
In advance, thanks a lot!!!
On WooCommerce variable product pages, product variation data is stored in the data-product_variations attribute of the multi-select <form class="variation_form"> element. The variation data is stored in JSON format which you can then decode using the JSON.parse() method. There is no need to output this data yourself via PHP as WooCommerce already does it for you.
The JSON stored in the data-product_variations attribute includes the following price related properties:
display_price
regular_price
sale_price
With a little bit of jQuery/JS, you can easily output or mutate the default or selected variation pricing with the above properties.
Good Luck!
I currently have a wordpress site setup using woocommerce and gravity forms plugins. I am selling bike wheels and on my product page I use gravity forms to display different customization options. the options are different if they select one wheel or two wheels.
What I'm trying to achieve
I want to add a 5% discount if two wheels are selected and 10% if four+ are selected. This discount is applied to the product as it is added to the cart.
I am attempting to create a custom plugin that uses javascript to get the value from the gravity forms input, and hooks into woocommerce to edit the total price before adding it to the cart.
What I have so far
custom.js
jQuery(document).ready(function () {
jQuery('.cart').submit(function () {
var noOfWheels = jQuery(".rdoWheel input[type='radio']:checked").val();
console.log(noOfWheels)
var data = {
action: 'my_discount',
wheels: noOfWheels
};
jQuery.ajax({
type: 'POST',
url: discountAjax.ajax_url,
data: data,
success: function (data) {
//do nothing
},
});
return false;
});
});
discount.php
add_action('wp_enqueue_scripts', 'load_script');
function load_script() {
wp_enqueue_script('discount', plugin_dir_url( __FILE__ ) . 'custom/custom.js', array( 'jquery' ) );
wp_localize_script('discount', 'discountAjax', array('ajaxurl' => admin_url('admin-ajax.php')));
}
add_action('wp_ajax_woocommerce_discount', 'calculate', 10);
add_action('wp_ajax_nopriv_woocommerce_discount', 'calculate', 10);
function calculate() {
if (isset($_POST['wheels'])) {
global $woocommerce;
$wheels = $_POST['wheels'];
if ($wheels === "1") {
$val = 0;
} elseif ($wheels === "2"){
$val = 10;
}
session_start();
$_SESSION['val'] = $val;
}
}
add_action('woocommerce_before_calculate_totals', 'add_discount');
function add_discount( $cart_object) {
#session_start();
if (isset($_SESSION['val'])) {
$wheels = $_SESSION['val'];
foreach ( $cart_object->cart_contents as $key => $value ) {
$c_price = $value['data']->price;
$discountAmount = $c_price * $wheels/100;
$value['data']->price = $value['data']->price - $discountAmount;
}
//for testing purpose
echo $_SESSION['val'];
echo 'completed';
unset($_SESSION['val']);
}
}
whats happening
It seems the woocommerce function is not firing at all. when i check with firebug I see my ajax request go through okay then nothing else. If i remove everything except for the add_discount function then it goes through and applies the discount. I cant seem to get it to work with javascript/ajax.
So I'm trying to hide certain ship methods in Woocommerce based on a product tag. The main problem I face is my own lack PHP knowledge so I frankensteined the following code together with the help of some very friendly folks:
add_filter( 'woocommerce_available_shipping_methods', 'hide_shipping_based_on_tag' , 10, 1 );
function check_cart_for_share() {
// load the contents of the cart into an array.
global $woocommerce;
$cart = $woocommerce->cart->cart_contents;
$found = false;
// loop through the array looking for the tag you set. Switch to true if the tag is found.
foreach ($cart as $array_item) {
if (isset($array_item['product_tag']) && $array_item['product_tag'] == "CHOSEN_TAG") { // Replace "CHOSEN_TAG" with what ever tag you want
$found = true;
break;
}
}
return $found;
}
function hide_shipping_based_on_tag( $available_methods ) {
// use the function abve to check the cart for the tag.
if ( check_cart_for_share() ) {
// remove the rate you want
unset( $available_methods['flat_rate'] ); // Replace "flar_rate" with the shipping option that yu want to remove.
}
// return the available methods without the one you unset.
return $available_methods;
}
I understand that this code is by no means universal and thus the variables will be different from case to case but perhaps someone can tell me if something looks off in the code. Much appreciated
No doubt you have sorted this by now but your code was a good start for me ... and since I sorted it I have published it below. Your problem was that woocommerce doesn't have the product_tag in the cart array so you have to go and get it.
/* !Hide Shipping Options Woocommerce */
add_filter( 'woocommerce_available_shipping_methods', 'hide_shipping_based_on_tag' , 10, 1 );
function check_cart_for_share() {
// load the contents of the cart into an array.
global $woocommerce;
$cart = $woocommerce->cart->cart_contents;
$found = false;
// loop through the array looking for the tag you set. Switch to true if the tag is found.
foreach ($cart as $array_item) {
$term_list = wp_get_post_terms( $array_item['product_id'], 'product_tag', array( "fields" => "names" ) );
if (in_array("Heavy",$term_list)) { // Replace "Heavy" with what ever tag you want
$found = true;
break;
}
}
return $found;
}
function hide_shipping_based_on_tag( $available_methods ) {
// use the function above to check the cart for the tag.
if ( check_cart_for_share() ) {
// remove the rate you want
unset( $available_methods['flat_rate'] ); // Replace "flat_rate" with the shipping option that you want to remove.
}
// return the available methods without the one you unset.
return $available_methods;
}
You can use shipping class of Woocommerce to achieve this.
Here is the step by step instructions.
Create a shipping class (woocommerce->settings->shipping->shipping classes).
Associate this shipping class with products (that you wand to hide shipping methods for)
Use this snippet. (copy and pate to function.php).
For more information about the snippet is available here.