PHP code for automatically change WooCommerce order status - php

I would like to change the status of every new WooCommerce order depending on a custom field (shopart) with PHP.
I already tried to write a function in the functions.php file but I failed.
// set Custom Order Status at WooCommerce Checkout Process
add_action( 'woocommerce_thankyou', 'uebes_thankyou_change_order_status' );
function uebes_thankyou_change_order_status( $order_id ){
if( ! $order_id ) return;{
$order = wc_get_order( $order_id );
// update order status dependimg to custom field shopart
if(get_post_meta($order->id,'shopart',true) == 'Shop Vorbestellungen'){
$order->update_status( 'vorbestellung' );
}else{
$order->update_status( 'bestellung-neu' );
}
}
}

// set Custom Order Status at WooCommerce Checkout Process
add_action('woocommerce_thankyou', 'uebes_thankyou_change_order_status', 10, 1);
function uebes_thankyou_change_order_status($order_id) {
if (!$order_id)
return;
//create an order instance
$order = wc_get_order($order_id);
// update order status dependimg to custom field shopart
if (get_post_meta($order_id, 'shopart', true) == 'Shop Vorbestellungen') {
$order->update_status('vorbestellung');
} else {
$order->update_status('bestellung-neu');
}
}

Related

Hide order statuses in dropdown based on order status in WooCommerce edit order page

I want to hide order statuses in the WooCommerce order status dropdown under specific scenarios:
If status is pending payment hide completed
If status is processing hide pending payment
I still want to display all these order statuses in the order overview list.
All I can find is to unset an order status completely:
function so_39252649_remove_processing_status ($statuses) {
if (isset($statuses['wc-processing'])) {
unset($statuses['wc-processing']);
}
return $statuses;
}
add_filter('wc_order_statuses', 'so_39252649_remove_processing_status');
But this will of course also remove it from the order overview list, I just want to hide it in the dropdown on the order edit page, but I cant find a hook for this.
Is jQuery my only choice for this?
You can use the following, comments with explanations added in the code.
So you get:
// Admin order edit page: order status dropdown
function filter_wc_order_statuses( $order_statuses ) {
global $post, $pagenow;
// Target edit pages
if( $pagenow === 'post.php' && isset($_GET['post']) && $_GET['action'] == 'edit' && get_post_type($_GET['post']) === 'shop_order' ) {
// Get ID
$order_id = $post->ID;
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Is a WC order
if ( is_a( $order, 'WC_Order' ) ) {
// Get current order status
$order_status = $order->get_status();
// Compare
if ( $order_status == 'pending' ) {
unset( $order_statuses['wc-completed'] );
} elseif ( $order_status == 'processing' ) {
unset( $order_statuses['wc-pending'] );
}
}
}
return $order_statuses;
}
add_filter( 'wc_order_statuses', 'filter_wc_order_statuses', 10, 1 );

How to automatically change woocommerce processing status to completed

How to change in woocommerce order status from processing to completed
?
I found snippet, but it only changes status if you go to thank you page, but if my customer decides just to close paypal page and don't go to thank you page ?
Then it is still processing, tested it already. I need automatically to detect processing status and change it to processing.
This will check for when the order changes status. If the status changes to processing, it will set the status to completed. Note that it does go through processing, so the user will probably get two emails back to back. You can disable one of the emails in the WC settings dashboard.
function wc_status_change($order_id,$old_status,$new_status) {
$order = new WC_Order( $order_id );
if($order->status == 'processing'){
$order->update_status('completed');
}
}
In your case you have two options the first may not work as it is related to previous versions of woocommerce but the second one should work
add the code to your functions.php
1º
add_filter( 'woocommerce_payment_complete_order_status', 'update_order_status_woo', 10, 2 );
function update_order_status_woo( $order_status, $order_id ) {
$order = new WC_Order( $order_id );
if ( $order_status == 'processing' && ( 'on-hold' == $order->status || 'pending' == $order->status || 'failed' == $order->status ) ) {
return 'completed';
}
return $order_status;
}
2º
add_action('woocommerce_order_status_changed', 'auto_update_processing_to_complete');
function auto_update_processing_to_complete($order_id)
{
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
if ($order->data['status'] == 'processing') {
$order->update_status( 'completed' );
}
}

Change Woocommerce Order Status based on Shipping Method

The idea here is that when an order comes in with an "express delivery" as Shipping Method, the order status is updated to On-Hold.
As there I have some different "express delivery" Shipping Method rates I thought that by using stristr() to see if the word 'express' appears anywhere in the formatted shipping method title. But I seem to be missing something as I don't get anything.
How can I check if the Order shipping method is an "express delivery" to be able to update the order status?
Here is the code that I have:
add_action( 'woocommerce_thankyou', 'express_orders_4865', 10, 1 );
function express_orders_4865( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$shipping_method = $order->get_shipping_method();
if (stristr($shipping_method, 'express') === TRUE) {
$order->update_status('on-hold');
} else {
return;
}
}
EDIT-----------------------------------------------------------
For anyone using Woocommerce Table Rate Shipping the get_method_id returns the table rate id so i used get_method_title instead as below, if there is a better way please comment...
add_action( 'woocommerce_thankyou', 'express_shipping_update_order_status', 10, 1 );
function express_shipping_update_order_status( $order_id ) {
if ( ! $order_id ) return;
$search = 'Express'; // The needle to search in the shipping method ID
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the WC_Order_Item_Shipping object data
foreach($order->get_shipping_methods() as $shipping_item ){
// When "express delivery" method is used, we change the order to "on-hold" status
if( strpos( $shipping_item->get_method_title(), $search ) !== false ){
$order->update_status('on-hold');
break;
}
}
}
I prefer to use the faster and less memory intensive function strpos() instead as the shipping method ID is alway in lowercase (like a kind of slug).
So is better the get the WC_Order_Item_Shipping object data for this case, using the available methods.
So the code should be:
add_action( 'woocommerce_thankyou', 'express_shipping_update_order_status', 10, 1 );
function express_shipping_update_order_status( $order_id ) {
if ( ! $order_id ) return;
$search = 'express'; // The needle to search in the shipping method ID
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the WC_Order_Item_Shipping object data
foreach($order->get_shipping_methods() as $shipping_item ){
// When "express delivery" method is used, we change the order to "on-hold" status
if( strpos( $shipping_item->get_method_title(), $search ) !== false && ! $order->has_status('on-hold')){
$order->update_status('on-hold');
break;
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works…
So the code above didn't work for me, i had someone in a FB group help me debug it and this was the final one that worked for me
add_action( 'woocommerce_thankyou', 'express_shipping_update_order_status', 10, 1 );
function express_shipping_update_order_status( $order_id ) {
if ( ! $order_id ) return;
$search = 'express'; // The needle to search in the shipping method ID
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the WC_Order_Item_Shipping object data
foreach($order->get_shipping_methods() as $shipping_item ){
// When "express delivery" method is used, we change the order to "on-hold" status
if( strpos( $shipping_item->get_method_title(). $search ) !== false ){
$order->update_status('on-hold');
$order->save();
break;
}
}
}
My solution assumes that the normal status for a new order is PROCESSING.
So when an order is changed to PROCESSING, check the shipping method and if it matches, then change it to ON-HOLD.
add_action('woocommerce_order_status_changed', 'jds_auto_change_status_by_shipping_method');
function jds_auto_change_status_by_shipping_method($order_id) {
// If the status of an order is changed to PROCESSING and the shipping method contains specific text then change the status.
if ( ! $order_id ) {
return;
}
global $product;
$order = wc_get_order( $order_id );
if ($order->data['status'] == 'processing') { // if order status is processing
$shipping_method = $order->get_shipping_method();
if ( strpos($shipping_method, 'express') !== false ) { // if shipping method CONTAINS this text
$order->update_status('on-hold'); // change status to this
}
}
}
Note that $shipping_method returns the human readbale version of the shipping method that the customer sees, so you need to match exactly how the word 'express' appears to customer... is it 'express' or 'Express' or 'EXPRESS'

Change order status when order has backorder items in it

In WooCommerce, How to change the on-hold order status to something else, if this order has back-ordered items in it?
I have tried to use a custom function hooked in woocommerce_order_status_on-hold action hook without success.
Can anyone help me on this issue?
Thanks.
Here is a custom function hooked in woocommerce_thankyou action hook, that will change the order status if this order has a status "on-hold" and if it has any backorder products in it.
You will have to set in the function the desired new status slug change.
Here is that custom function (code is well commented):
add_action( 'woocommerce_thankyou', 'change_paid_backorders_status', 10, 1 );
function change_paid_backorders_status( $order_id ) {
if ( ! $order_id )
return;
// HERE below set your new status SLUG for paid back orders
$new_status = 'completed';
// Get a an instance of order object
$order = wc_get_order( $order_id );
// ONLY for "on-hold" ORDERS Status
if ( ! $order->has_status('on-hold') )
return;
// Iterating through each item in the order
foreach ( $order->get_items() as $item ) {
// Get a an instance of product object related to the order item
$product = $item->get_product();
// Check if the product is on backorder
if( $product->is_on_backorder() ){
// Change this order status
$order->update_status($new_status);
break; // Stop the loop
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
The code is tested and works.
function mysite_hold($order_id) {
$order = new WC_Order($order_id);
$items = $order->get_items();
$backorder = FALSE;
foreach ($items as $item) {
if ($item['Backordered']) {
$backorder = TRUE;
break;
}
}
if($backorder){
$order->update_status('completed'); //change your status here
}
}
add_action('woocommerce_order_status_on-hold', 'mysite_hold');
//You may need to store your backorder info like below
wc_add_order_item_meta($item_id, 'Backordered', $qty - max(0, $product->get_total_stock()));
Please try this snippet
edit code error on // Get a an instance of product object related to the order item
$product = version_compare( WC_VERSION, '3.0', '<' ) ? wc_get_product($item['product_id']) : $item->get_product();

update woocommerce order status after payment process complete and redirect to store

I am using woo-commerce for my shopping site. I want to update the order status to complete after payment was made and then return to a success page.
I used the following code:
add_filter( 'woocommerce_payment_complete_order_status', 'my_change_status_function', 10, 2 );
function my_change_status_function ($order_status, $order_id) {
$order = new WC_Order($order_id);
return 'completed';
}
But this function is called before the payment was made and redirects to the payment page.
I want to change the status after the payment was completed and then return to redirect URL.
Here is my redirect link:
http://example.com/checkout/order-received/82/?key=wc_order_5614e28c9d183&state=return
But the status is not changing when I use the woocommerce_payment_complete_order_status hook.
The hook should be called after the payment is completed.
Try using the following code in your plugin
add_action( 'woocommerce_payment_complete', 'my_change_status_function' );
function my_change_status_function( $order_id ) {
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Check out this piece of code
add_action('woocommerce_checkout_order_processed', 'do_something');
function do_something($order_id) {
$order = new WC_Order( $order_id );
// Do something
}
For Cash On Delivery method, this worked for me:
add_filter( 'woocommerce_cod_process_payment_order_status', 'prefix_filter_wc_complete_order_status', 10, 3 );
function prefix_filter_wc_complete_order_status( $status, $order ) {
return 'on-hold';
}
For most other methods, this worked:
add_filter( 'woocommerce_payment_complete_order_status', 'prefix_filter_wc_complete_order_status', 10, 3 );
function prefix_filter_wc_complete_order_status( $status, $order_id, $order ) {
return 'on-hold';
}
Working with WooCommerce v4.4, other answers were not working for me. I had to do it this way: https://stackoverflow.com/a/64285242/7198947

Categories