My customer wants to enable for some specific customers to pay afterwards via invoice.
So i've added an extra field in the user profiles, where he can select yes/no.
This field works fine and saves properly.
Depending on the choice:
no = default webshop behavior and customer needs to pay direct.
yes = customer can order items without paying, he'll get an invoice later on.
Also tried different payment methods, but they are available for everybody, i only want them for specific users.
Now i've tried based on that field in the functions.php to add a conditional filter like so:
if (esc_attr( get_the_author_meta( 'directbetalen', $user->ID ) ) == 'no') {
add_filter('woocommerce_cart_needs_payment', '__return_false');
}
But it doesn't seem to work?
I want payment to be skipped when the field is set to no.
Else proceed as normal and customer needs to pay.
Using WordPress get_user_meta() function, try the following :
add_filter( 'woocommerce_cart_needs_payment', 'disable_payment_for_specific_users' );
function show_specific_payment_method_for_specific_users( $needs_payment ) {
if ( get_user_meta( get_current_user_id(), 'directbetalen', true ) === 'no' ) {
$needs_payment = false;
}
return $needs_payment;
}
Code goes in functions.php file of your active child theme (or active theme). It should work.
Related
Is it possible to automatically copy the value of a Customer's custom field to an Order's custom field when this customer places the order?
Should it be done using any plugin/extension or thru customized coding behind the scenes?
This custom field does not need to be displayed on customer order view. We just need it to distinguish whether the order was placed by Consumer or Wholesale when we get it thru API.
I'm totally new in this system, i did a lot of research but couldn't find any direction for this.
Any advice/suggestion would be very appreciated.
You can use woocommerce_thankyou hook to add this user data to the order meta data:
add_action( 'woocommerce_thankyou', 'orders_from_processing_to_pending', 10, 1 );
function orders_from_processing_to_pending( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
$user_id = get_current_user_id();
//Set HERE the meta key of your custom user field
$user_meta_key = 'some_meta_key';
// Get here the user custom field (meta data) value
$user_meta_value = get_user_meta($user_id, $user_meta_key, true);
if ( ! empty($user_meta_value) )
update_post_meta($order_id, $user_meta_key, $user_meta_value);
else
return;
}
Code goes in function.php file of your active child theme (active theme or in any plugin file).
This code is tested and works.
After, if you want to display that value on admin edit order backend or in frontend customer view order and emails notifications, you will have to use some more code and some other hooks…
I use WooCommerce to manually take orders via the telephone / email etc. I use the backend to record the orders manually adding the orders.
At present, when generating an order as 'pending payment' as the status the stock is automatically reduced / deducted. I do not want this to happen. Ideally I only want stock to be reduced when the order is marked as in 'processing' as then payment would of then been taken.
I understand this is how WooCommerce works back is there a way to avoid stock being reduced until a certain status has been selected?
I have tried the below code within functions.php and used the 'on-hold' status to test but the stock is still reduced.
add_filter( 'woocommerce_can_reduce_order_stock', 'wcs_do_not_reduce_onhold_stock', 10, 2 );
function wcs_do_not_reduce_onhold_stock( $reduce_stock, $order ) {
if ( $order->has_status( 'on-hold' )) {
$reduce_stock = false;
}
return $reduce_stock;
}
I wonder if it because I am adding the order as an admin? I know this is how WooCommerce works but ideally I need a method of overriding the 'pending payment' status when creating an order both within the draft and creation stage until marked as 'processing'.
Any help would be fantastic.
Try this adding to functions.php
Note: not tested.
function reduce_stock_processing($order_id) {
wc_reduce_stock_levels($order_id);
}
add_action('woocommerce_order_status_processing', 'reduce_stock_processing');
I'm currently using a Woocommerce session to save information that the user inputs on the cart page which affects a fee added to the transaction.
I need to be able to access this information right after the order has been completed to make necessary updates to the user's account.
I figured woocommerce_thankyou would be a good hook to use, but unfortunately the session only seems to be available half of the time.
Are there any better hooks to use where I could confirm that the purchase had been completed and the session information would be available?
You need to save that session data as custom order meta data, to be able to use it afterwards (replace my_key, in the code below, with the correct session key):
// Add custom order meta data with temporary data from WC_Session
add_action( 'woocommerce_checkout_create_order', 'add_session_data_as_custom_order_meta_data', 10, 2 );
function add_session_data_as_custom_order_meta_data( $order, $data ) {
if ( $session_data = WC()->session->get('my_key') ) {
$order->update_meta_data( '_session_data', $session_data );
}
}
Code goes on function.php file of your active child theme (or theme). Tested and works.
Then to access the data you will use th WC_Data method get_meta() on the WC_Order Object:
$session_data = $order->get_meta('_session_data');
Or also using get_post_meta() function from a defined order Id:
$session_data = get_post_meta( $order_id, '_session_data', true );
I've made a Woocommerce giftshop for a client.
Their customers are other business that let their employees select their gift through the webshop. Each business have 1 login that all employees use.
As of right now, every user is only allowed 1 item in their cart.
If another product is selected, it will overwrite the previous.
Today I was informed that they wish to expand so it will be possible for select users/user roles to have more than 1 product in their cart and "purchase" them.
Money transactions are not handled directly on the webshop, so purchasing the products sends a list to my client and they take it from there
The current code I use to impose this limit is the following:
add_filter( 'woocommerce_add_to_cart_validation', 'custom_only_one_in_cart', 99, 2 );
function custom_only_one_in_cart( $passed, $added_product_id ) {
// empty cart first: new item will replace previous
wc_empty_cart();
// display a message if you like
wc_add_notice( 'Max number of items in cart reached!', 'notice' );
return $passed;
}
So I'm looking for ideas on how to implement this on specific users or user roles, so the end result will be that most users can only pick one, while a few select user can pick more.
I've already been looking around a lot for a suitable solution, but I haven't been able to find one as of yet.
The solution doesn't have to incorporate the code I provided, either in its current state or in a variation of it, all suitable solutions are welcome.
Any help is appreciated.
In the following code will restrict add to cart to only one item based on defined allowed user roles:
add_filter( 'woocommerce_add_to_cart_validation', 'user_roles_only_one_in_cart', 50, 3 );
function user_roles_only_one_in_cart( $passed, $product_id, $quantity ) {
// HERE define the User roles that are allowed to buy multiple items:
$allowed_user_roles = array('special_customer','administrator', 'shop_manager');
$user = wp_get_current_user();
if( array_intersect( $allowed_user_roles, $user->roles ) )
return $passed;
// Check if cart is empty
if( ! WC()->cart->is_empty() ){
// display an error notice
wc_add_notice( __("Only one item in cart is allowed!", "woocommerce"), "error" );
// Avoid add to cart
$passed = false;
}
return $passed;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
For user roles creation and management you can use User Role Editor plugin (for example).
In WoCommerce, I would like to disable particular payment methods and show particular payment methods for a subscription products in WooCommerce (and vice versa).
This is the closest thing we've found but doesn't do what I am expecting.
Yes, there are plugins that will do this but we want to achieve this without using another plugin and without making our stylesheet any more nightmarish than it already is.
Any help on this please?
Here is an example with a custom hooked function in woocommerce_available_payment_gateways filter hook, where I can disable payment gateways based on the cart items (product type):
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$prod_variable = $prod_simple = $prod_subscription = false;
// Get the WC_Product object
$product = wc_get_product($cart_item['product_id']);
// Get the product types in cart (example)
if($product->is_type('simple')) $prod_simple = true;
if($product->is_type('variable')) $prod_variable = true;
if($product->is_type('subscription')) $prod_subscription = true;
}
// Remove Cash on delivery (cod) payment gateway for simple products
if($prod_simple)
unset($available_gateways['cod']); // unset 'cod'
// Remove Paypal (paypal) payment gateway for variable products
if($prod_variable)
unset($available_gateways['paypal']); // unset 'paypal'
// Remove Bank wire (Bacs) payment gateway for subscription products
if($prod_subscription)
unset($available_gateways['bacs']); // unset 'bacs'
return $available_gateways;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
All code is tested on Woocommerce 3+ and works.
This is just an example to show you how things can work. You will have to adapt it
This code has been very useful to me, but there is an error in it that I had to fix: the line
$prod_variable = $prod_simple = $prod_subscription = false;
must be put OUTSIDE (before) the FOREACH otherwise it will reset the flag everytime a new item is executed. I my case, I needed to unset a specific payment method whenever a subscription product was on the cart. As it is, this code will work only if there is just a single subscription product. If I put another different item on cart, the flag will be turn to false again and the payment method will load. Putting the line outside the FOREACH will fix this problem.