Remove Tax based on Customer ID Woocommerce [duplicate] - woocommerce

In my woocommerce web site, I have enable Tax in general WooCommerce settings.
I would like to disable tax for a specific user role programmatically ( with any hooks ), from my shop, checkout page and from order email.
How could I achieve this?
Thanks

2020 update
You can't disable WooCommerce tax for a specific user role programmatically, but you can apply for a specific user role a zero tax rate.
First you need to have this specific user role set in worpress. If it's the case, let say that this custom user role is 'resellers' for my code example.
Second, you have to enable in WooCommerce settings a zero tax rate:
And then for each country, you will have to set this zero tax rate:
Third - Then this hooked function will do the trick:
Update - Since WooCommerce 3 use the following:
function zero_rate_for_custom_user_role( $tax_class, $product ) {
// Getting the current user
$current_user = wp_get_current_user();
$current_user_data = get_userdata($current_user->ID);
// <== <== <== <== <== <== <== Here you put your user role slug
if ( in_array( 'resellers', $current_user_data->roles ) )
$tax_class = 'Zero Rate';
return $tax_class;
}
add_filter( 'woocommerce_product_get_tax_class', 'wc_diff_rate_for_user', 10, 2 );
add_filter( 'woocommerce_product_variation_get_tax_class', 'wc_diff_rate_for_user', 10, 2 );
Before WooCommerce version 3 use the following:
function zero_rate_for_custom_user_role( $tax_class, $product ) {
// Getting the current user
$current_user = wp_get_current_user();
$current_user_data = get_userdata($current_user->ID);
// <== <== <== <== <== <== <== Here you put your user role slug
if ( in_array( 'resellers', $current_user_data->roles ) )
$tax_class = 'Zero Rate';
return $tax_class;
}
add_filter( 'woocommerce_product_tax_class', 'zero_rate_for_custom_user_role', 10, 2 );
You will just need to put instead of 'resellers' your desired user role slug.
This code goes in functions.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and fully functional.
Reference: WooCommerce - Enabling "Zero rate" tax class to some specific user roles

Related

Is there a reason the "Emails" tab in WooCommerce Settings breaks after the use of custom code?

I have used the following custom code.
add_filter( 'woocommerce_email_recipient_new_order', 'custom_wc_email_recipient_new_order', 10, 2 );
function custom_wc_email_recipient_new_order( $recipient, $order ) {
// Get the user ID of the order's creator
$user_id = $order->get_user_id();
// Get the user's role
$user = get_userdata( $user_id );
$user_role = $user->roles[0];
// Only send the email to the admin email if the customer has the specified user role
if ( $user_role == 'role1' ) {
return $recipient .= ', admin#website.com';
}
// Return the original recipient for all other user roles
return $recipient;
}
The code works perfectly fined and does what it is required to do, however, once the code has been used once (so once an order has been placed) if I try to access the "Emails" tab in "WooCommerce > Settings", I get a fatal error on the website and all I see is the below image.
Is there a reason for this, and if so, a way I can fix it?
EDIT - Added part of the error log:
[20-Dec-2022 17:12:00 UTC] WordPress database error Unknown column 'wp_postmeta.post_id' in 'where clause' for query SELECT meta_id FROM wp_8hkq051x71_postmeta,
(SELECT DISTINCT post_id FROM wp_8hkq051x71_postmeta
WHERE (meta_key = '_billing_country' OR meta_key='_shipping_country') AND meta_value='UA')
AS states_in_country
WHERE (meta_key='_billing_state' OR meta_key='_shipping_state')
AND meta_value='CV'
AND wp_postmeta.post_id = states_in_country.post_id
LIMIT 100 made by do_action_ref_array('action_scheduler_run_queue'), WP_Hook->do_action, WP_Hook->apply_filters, ActionScheduler_QueueRunner->run, ActionScheduler_QueueRunner->do_batch, ActionScheduler_Abstract_QueueRunner->process_action, ActionScheduler_Action->execute, do_action_ref_array('woocommerce_run_update_callback'), WP_Hook->do_action, WP_Hook->apply_filters, WC_Install::run_update_callback, wc_update_721_adjust_ukraine_states, Automattic\WooCommerce\Database\Migrations\MigrationHelper::migrate_country_states, Automattic\WooCommerce\Database\Migrations\MigrationHelper::migrate_country_states_for_orders
I have many lines like the one above, the only part that seems to change on each line is the:
AND meta_value='CV'
The CV changes to CH, CK, KS, etc.
Second Edit - Code Fix
The initial problem with the code was a WooCommerce bug. With that bug solved, I still couldn't modify email recipients in the WooCommerce Emails tab in the Settings. To be able to modify recipients there you need to use the following modified code.
add_filter( 'woocommerce_email_recipient_new_order', 'custom_wc_email_recipient_new_order', 10, 2 );
function custom_wc_email_recipient_new_order( $recipient, $order ) {
if ( $order ) {
// Get the user ID of the order's creator
$user_id = $order->get_user_id();
// Get the user's role
$user = get_userdata( $user_id );
$user_role = $user->roles[0];
// Only send the email to the admin email if the customer has the specified user role
if ( $user_role == 'role1' ) {
return $recipient .= ', admin#website.com';
}
// Return the original recipient for all other user roles
return $recipient;
}
return $recipient;
}
Thanks for posting the error log, now it all makes sense. It's a database error, it says wp_postmeta.post_id is missing. This happens because you are using a custom database prefix wp_8hkq051x71 and some code that generated this SQL wasn't using $wpdb->postmeta or $wpdb->prefix. Instead, there was a hardcoded wp_postmeta value and that table really doesn't exists in your database.
But how that happened?
WooCommerce team made some changes to country states, in this case Ukrainian states and they made a bug inside the update script.
They already fixed it 19 hours ago: https://github.com/woocommerce/woocommerce/commit/6a1a7d7e15f488064f872020d42b7a58a2980c38
So just update WooCommerce to the latest version and the bug will disappear.
Also, I would highly recommend you to use only stable releases of WooCommerce instead of latest dev versions.
Current stable version is 7.1.1 and current dev version with included fix for this issue is 7.2.1 (https://github.com/woocommerce/woocommerce/releases/tag/7.2.1)
The problem is not related to your custom_wc_email_recipient_new_order at all. It's just a coincidence that you noticed this bug after you added your change.

Get the order ID on the final checkout page when a customer purchased a product in WooCommerce

I'm developing a plugin that needs to get the order ID on the final checkout page when a customer purchased a product. How do I do that?
I tried
global $order
var_dump($order);
And all I see is "DESC". I need to access the current order of the customer who is looking at the page.
I need to get the order id in the frontend and add that ID to a script, also on the front end, so that when a client orders a product and pays, the page will load, show them the "Thank you, here is your order number: xxx". At that moment I need my script to, for example, execute a console.log("The oder ID is:", order_id);
To get the order ID on the final checkout page when a customer purchased a product you can use the woocommerce_thankyou hook, where the callback function already contains the order ID.
// define the woocommerce_thankyou callback
function action_woocommerce_thankyou( $order_id ) {
echo "Thank you, here is your order ID: " . $order_id;
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Customer billing country
$billing_country = $order->get_billing_country();
// etc..
};
// add the action
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );

How to get ACF data from WooCommerce customers for order export

On a Wordpress-Shop I use WooCommerce (WC) with Advenced-Custom-Fields (ACF)
and WP-All-Import (WPAI) + WP-All-Export (WPAE).
I added a ACF field CustomerNumber to the WC-Customer (which enhanced the WP-User).
On the WPAI-XML-Import I set the CustomerNumber with a value from a ERP.
So all customers have a unique CustomerNumber.
I now need to export the WC-Orders (to import them in the ERP again).
The Order-XML must include the CustomerNumber from the Customer belongs to the Order.
As I see, the other standard fields from the customer – like name and address – are copied automatically to the order (by WooCommerce itself).
My question is now: How I have to do this for the ACF’s?
Did I have to do this by code on my own? Adding the same AC-fields to the WC-Order and hook into the order checkout and copy the values from the customer to the order?
Or is there some kind of setup which do that and which I did not recognize?
Thx
I did not really found an answer.
My current solution is now as I described it in my question.
I added a new rule for these acf to also make them available on the orders.
Then I added a hook to new created orders, determine the acf from the user and copied the necessary values into the order acf.
function di_woocommerce_new_order( $order_id ) {
$order = new WC_Order( $order_id );
if ( !$order ) return;
$customer_id = $order->get_customer_id();
if ( !$customer_id ) return;
$customer = new WC_Customer($customer_id);
if ( !$customer ) return;
$customer_number = $customer->get_meta('customernumber');
if ( !$customer_number ) return;
// add customer number
$order->add_meta_data('customernumber', $customer_number);
// update order modified timestamp
$order->add_meta_data('order_last_updated', current_time( 'mysql' ));
$order->save_meta_data();
}
add_action( 'woocommerce_checkout_order_processed', 'di_woocommerce_new_order', 10, 1);

Woocommerce "No Shipping methods" message: Customise message based on the Zipcode customer enters

Our store has been setup to process orders only within Sydney city. We manage this in Woocommerce by setting the allowed postcodes for a Flat Rate Delivery.
We are now extending deliveries to other other areas but only via telephone (no online orders for these new postcodes). Woocommerce displays a standard No Shipping message but we would to customise such that
Customer enters a postcode within the city, allow online orders. No
change to current behaviour.
Customer enters a postcode for which
telephone orders are allowed, show a customised message asking the
customer to make the call.
All other postcodes, disallow orders.
Any technical direction will be greatly appreciated.
Thanks.
Below code should help you. Change the value of array variable $zip_array in both the functions as a comma separated list of zip codes, which you want to show a custom message. Also, change the string value of $custom_msg to your custom message. More details, please refer this article.
// For Cart Page.
add_filter( 'woocommerce_no_shipping_available_html', 'wf_customize_default_message', 10, 1 );
// For Checkout page
add_filter( 'woocommerce_cart_no_shipping_available_html', 'wf_customize_default_message', 10, 1 );
function wf_customize_default_message( $default_msg ) {
$zip_array = array(
'30031',
);
if ( in_array( WC()->customer->get_shipping_postcode() , $zip_array) ) {
$custom_msg = "Call us for quotation - 1-800-XXX-XXXX";
if( empty( $custom_msg ) ) {
return $default_msg;
}
return $custom_msg;
}
return $default_msg;
}
add_filter('woocommerce_package_rates', 'wf_remove_shipping_options_for_particular_zip_codes', 8, 2);
function wf_remove_shipping_options_for_particular_zip_codes($rates, $package)
{
global $woocommerce;
$zip_array = array(
'30031',
);
if ( in_array( $woocommerce->customer->get_shipping_postcode() , $zip_array) ) {
$rates = array();
}
return $rates;
}

Wordpress - Change forum role from outside bbPress by checking user status

I would like to check the user status and update their bbPress forum role accordingly. (Not the Wordpress role.)
The purpose is to add functionality to the BP-Registration-Options plugin that moderates user registration (In BuddyPress. Currently the plugin sets the user status to 69 while the user is unapproved, and blocks access to BuddyPress functionality. However, the user is still able to login.
When they log-in, bbPress automatically sets the user forum role according to your setting in the back end. In this case it is set to 'spectator'. When the user is approved by the admin their status changes and I want it to also update the bbPress role to 'participant'.
Here is my first attempt:
function bp_registration_options_additional() {
if ( is_user_logged_in() ) {
$user_ID = get_current_user_id();
$user = get_userdata( $user_ID );
if (69 !== $user->user_status ) {
// Here is where I need help.
//How to set the bbPress forum role to 'Participant'?
}
}
}
add_action( 'wp_loaded', 'bp_registration_options_additional' );
Thanks!
WP: 3.8
bbPress: Version 2.5.2
EDIT: A bit of additional information. The meta_key for the forum roles is: wp_capabilities. The meta_value of a user with the forum role 'spectator; is: a:2:{s:10:"subscriber";b:1;s:13:"bbp_spectator";b:1;}
Had the same requirement - to update the wp_capabilities field -
$wp_user_capabilities_arr = array(
"subscriber" => true,
"bbp_participant" => true
);
update_user_meta($wp_user_id, "wp_capabilities", $wp_user_capabilities_arr);
And after update the data looks like:
a:2:{s:10:"subscriber";b:1;s:15:"bbp_participant";b:1;}

Resources