I am currently working on a WordPress project using WooCommerce and I need a really specific feature (not included in WooCommerce):
How to increase stock when an order is complete instead of decreasing it ?
What I have found so far is that I might need to use Woocommerce API in order to accomplish that WC_AJAX::increase_order_item_stock();. Nevertheless I am not really comfortable using complex PHP...
Do you have some lines of thinking to accomplish this?
Maybe using a plugin (which I did not find)? Or with raw code?
To sum up everything: I want to build a website for a restaurant with an inventory management and the possibility for cooks to order goods from different suppliers. So when a cook order something from the woocommerce shop page, purchased items's inventory have to increase and not decrease.
I have tried different things like 'WC Vendors' or 'Marketplace' but without success…
Thanks.
You could try This custom function hooked in woocommerce_order_status_completed action hook, that will increase back each product stock with the items quantity of this order when status is set to completed:
add_action( 'woocommerce_order_status_completed', 'action_on_order_completed' , 10, 1 );
function action_on_order_completed( $order_id )
{
// Get an instance of the order object
$order = wc_get_order( $order_id );
// Iterating though each order items
foreach ( $order->get_items() as $item_id => $item_values ) {
// Item quantity
$item_qty = $item_values['qty'];
// getting the product ID (Simple and variable products)
$product_id = $item_values['variation_id'];
if( $product_id == 0 || empty($product_id) ) $product_id = $item_values['product_id'];
// Get an instance of the product object
$product = wc_get_product( $product_id );
// Get the stock quantity of the product
$product_stock = $product->get_stock_quantity();
// Increase back the stock quantity
wc_update_product_stock( $product, $item_qty, 'increase' );
}
}
The code works with simple or variables products that have their own stock management enabled. So may be you might need to make some changes on it, depending on your WooCommerce settings. This is just an example that gives you an idea, a way…
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code don't throw errors on WooCommerce version 2.6.x, and 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…
Does anyone have (or know of) a PHP code snippet solution to add automation say a checkbox to increase stock by quote list or bring back the original increase stock button in the order page; before sending out a quote ?
I have searched many days and hours for a code solution or a Plugin => Nothing.
I believe WooCommerce once used to have this button in the orders page but it is now not there, I am on Woo5.6.0, WP5.8 and PHP7.4
Thanks in advance.
So.. After re-posting my question again and reducing it to simplify and add focus, after I think a robot response closed my original question.
I looked at the suggestions that came up and "would you believe it" the post below was in the suggestion list.. I had not seen this before.
Increase stock (not decrease) after completed WooCommerce orders?
I had to test and change the call adapt the code a little to fit my store model..
I now have a working safe way of targeting only the stock from a quote list and only elevating the stock by the quote list amount (quantity) when I send out a quote.
The only downside to this is if another client comes along and sees the commission in stock they could place it in their basket and then it would not match the original quote sent out.
"Code to develop another time to find a way to reserve that elevated and allocated stock".
I did this after thinking about how to only trigger an action for a sent quote.
So a deep dive into Yiths Request a quote code to find the class where it changed the WooCommerce order status and came up with this.
Thanks to #loictheaztec he was responsible for this inspiration.
// Increase stock on pending quote order status - An experiment "ywraq-pending"
add_action( 'woocommerce_order_status_ywraq-pending', 'action_on_quote_sent' , 10, 1 );
function action_on_quote_sent( $order_id )
{
// Get an instance of the order object
$order = wc_get_order( $order_id );
// Iterating though each order items
foreach ( $order->get_items() as $item_id => $item_values ) {
// Item quantity
$item_qty = $item_values['qty'];
// getting the product ID (Simple and variable products)
$product_id = $item_values['variation_id'];
if( $product_id == 0 || empty($product_id) ) $product_id = $item_values['product_id'];
// Get an instance of the product object
$product = wc_get_product( $product_id );
// Get the stock quantity of the product
$product_stock = $product->get_stock_quantity();
// Increase back the stock quantity
wc_update_product_stock( $product, $item_qty, 'increase' );
}
}
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'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.