4

I have a product that people can print directly (shipping method 1) or choose to get it via shipping service (shipping method 2). So the order should auto complete if they choose to print it directly (shipping method 2) ONLY.

Is it possible to extend that code snippet from WooCommerce?

From docs I found this

/**
 * Auto Complete all WooCommerce orders.
 */
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order');
function custom_woocommerce_auto_complete_order( $order_id ) {
    if ( ! $order_id ) {
        return;
    }

    $order = wc_get_order( $order_id );
    $order->update_status( 'completed' );
}

Here is the working solution. BIG THANKS TO LoicTheAztec:

add_action( 'woocommerce_thankyou', 
'wc_auto_complete_paid_order_based_on_shipping_method', 20, 1 );
function wc_auto_complete_paid_order_based_on_shipping_method( $order_id ) {
if ( ! $order_id ) return;

// HERE define the allowed shipping methods IDs (can be names or slugs changing the code a bit)
$allowed_shipping_methods = array( '5' );

// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );

// Get the shipping related data for this order:
$shipping_item = $order->get_items('shipping');
$item = reset($shipping_item);
$item_data = $item->get_data();

// Get the shipping method name, rate ID and type slug
$method_rate_id = $item_data['instance_id'];  // Shipping method ID

// No updated status for orders delivered with Bank wire, Cash on 
delivery and Cheque payment methods.
$avoided_statuses = array( 'bacs', 'cod', 'cheque');
if ( in_array( $order->get_payment_method(), $avoided_statuses ) ){
return;
}
// update status to "completed" for paid Orders and a defined shipping 
method ID
elseif ( in_array( $method_rate_id, $allowed_shipping_methods ) ){
$order->update_status( 'completed' );
}
}
Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
Tob S
  • 43
  • 6

3 Answers3

0

I think what you're looking for is $order->has_shipping_method('name_of_method')

From: https://docs.woocommerce.com/wc-apidocs/class-WC_Abstract_Order.html#_has_shipping_method)

Peter HvD
  • 1,623
  • 1
  • 7
  • 14
  • Not quite. More like: if ( $order->has_shipping_method('bacs') || $order->has_shipping_method('cod') || $order->has_shipping_method('cheque') ) { – Peter HvD Jan 17 '18 at 15:30
  • the bacs, cod and cheque are payment methods. I added shipping in front only. payment methods should work like that way... – Tob S Jan 17 '18 at 15:48
  • Ah, of course... d’oh! In that case, instead of `'bacs' == get_post_meta($order_id, '_payment_method'` etc you should use `'bacs' == $order->get_payment_method()` – Peter HvD Jan 17 '18 at 16:11
0

First, get_post_meta($order_id, '_payment_method', true ) or $order->get_payment_method() are completely similar and do the same thing.
The difference is that the first one use a Wordpress function to access this data from wp_postmeta table and the 2nd one is a WC_Order method that will also access the same data from wp_postmeta table…
No one is better than the other.

New enhanced revisited code (see this thread for explanations).

What is the instance ID:
For example if the Shipping method rate Id is flat_rate:14, the instance Id is 14 (unique ID)

The new version code:

add_action( 'woocommerce_payment_complete_order_status', 'auto_complete_paid_order_based_on_shipping_method', 10, 3 );
function auto_complete_paid_order_based_on_shipping_method( $status, $order_id, $order ) {
    // HERE define the allowed shipping methods instance IDs
    $allowed_shipping_methods_instance_ids = array( '14', '19' );
    
    // Loop through order "shipping" items
    foreach ( $order->get_shipping_methods() as $shipping_method ) {
        if( in_array( $shipping_method->get_instance_id(), $allowed_shipping_methods_instance_ids ) ) {
            return 'completed';
        }
    }
    return $status;
}

Code goes in function.php file of the active child theme (or active theme). Tested and works.


Original answer:

The answer below comes from this similar answer I have made some time ago:
WooCommerce: Auto complete paid orders

add_action( 'woocommerce_thankyou', 'auto_complete_paid_order_based_on_shipping_method', 10, 1 );
function auto_complete_paid_order_based_on_shipping_method( $order_id ) {
    if ( ! $order_id ) return;

    // HERE define the allowed shipping methods IDs (can be names or slugs changing the code a bit)
    $allowed_shipping_methods = array( 'flat_rate:14', 'flat_rate:19' );

    // Get an instance of the WC_Order object
    $order = wc_get_order( $order_id );

    // Get the shipping related data for this order:
    $shipping_item = $order->get_items('shipping');
    $item = reset($shipping_item);
    $item_data = $item->get_data();

    // Get the shipping method name, rate ID and type slug
    $shipping_name = $item_data['name']; // Shipping method name
    $method_rate_id = $item_data['method_id'];  // Shipping method ID
    $method_arr = explode( ':', $method_rate_id );
    $method_type = $method_arr[0];  // Shipping method type slug

    // No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
    $avoided_statuses = array( 'bacs', 'cod', 'cheque');
    if ( in_array( $order->get_payment_method(), $avoided_statuses ) ){
        return;
    }
    // update status to "completed" for paid Orders and a defined shipping method ID
    elseif ( in_array( $method_rate_id, $allowed_shipping_methods ) ){
        $order->update_status( 'completed' );
    }
}

Code goes in function.php file of the active child theme (or active theme).

Tested and works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • FANTASTIC! :) Can you tell me one thing only. What is the "Shipping method type slug"? You wrote: " // HERE define the avoided shipping" and then named it $allowed_shipping.... is that correct? – Tob S Jan 17 '18 at 17:46
  • @TobS You can get the shipping method name as `Flat rate`, the Method ID like `flat_rate:18` and the slug is just `flat_rate` (so the slug method type) … you can change the code to have Names instead of slug type or Method ID too… – LoicTheAztec Jan 17 '18 at 17:50
  • 1
    Thank you :). Your first comment in the code is "// HERE define the avoided shipping..." but I think there you define the "allowed" shipping methods which update the status to completed? – Tob S Jan 17 '18 at 17:53
  • Accepted. Will try it tomorrow. Am I right, that I must change the "flat_rate:14" to my shipping method? And if I have one only I can use: $allowed_shipping_methods = array( 'flat_rate:14'); ? BIG BIG thanks to you :). – Tob S Jan 17 '18 at 18:36
  • @Tobs Of course yes. If there is any issue or problem regarding this, you can message me here. – LoicTheAztec Jan 17 '18 at 18:48
  • 1
    Have a great evening :)! – Tob S Jan 17 '18 at 19:35
  • Hi @LoicTheAztec The auto complete of the order with my specific shipping method: "$allowed_shipping_methods = array( 'flat_rate:5' );" if someone buy it via PayPal it is not working anymore. The status is "Processing" after paying via PayPal and use the specific method I defined above. I'm sure that it worked before. Did WC change anything? Thank you :)! – Tob S Sep 28 '18 at 20:29
  • @TobS Nothing related has changed and this code still perfectly works… So try to remember what actions have been done since the last time it was working... – LoicTheAztec Sep 28 '18 at 21:05
  • I found the solution. See my last answer :). – Tob S Sep 29 '18 at 13:24
  • Sorry. I don't know how stackoverflow handle things. Accepted yours again. – Tob S Sep 30 '18 at 11:59
0

That is my working solution (Thanks to LoicTheAztec):

add_action( 'woocommerce_thankyou', 
    'wc_auto_complete_paid_order_based_on_shipping_method', 20, 1 );
function wc_auto_complete_paid_order_based_on_shipping_method( $order_id ) {
    if ( ! $order_id ) return;

    // HERE define the allowed shipping methods IDs (can be names or slugs changing the code a bit)
    $allowed_shipping_methods = array( '5' );

    // Get an instance of the WC_Order object
    $order = wc_get_order( $order_id );

    // Get the shipping related data for this order:
    $shipping_item = $order->get_items('shipping');
    $item = reset($shipping_item);
    $item_data = $item->get_data();

    // Get the shipping method name, rate ID and type slug
    $method_rate_id = $item_data['instance_id'];  // Shipping method ID

    // No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
    $avoided_statuses = array( 'bacs', 'cod', 'cheque');
    if ( in_array( $order->get_payment_method(), $avoided_statuses ) ){
        return;
    }
    // update status to "completed" for paid Orders and a defined shipping method ID
    elseif ( in_array( $method_rate_id, $allowed_shipping_methods ) ){
        $order->update_status( 'completed' );
    }
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Tob S
  • 43
  • 6