Home » Wordpress » Restrict woocommerce order status by role

Restrict woocommerce order status by role

Posted by: admin November 30, 2017 Leave a comment

Questions:

I’m trying to make a workflow where shop managers can create orders and mark them as “pending payment”, “processing” but only admins can mark orders as “complete”, “failed” etc.

The closest I’ve found was in this post:

<?php 
if ( current_user_can(! 'administrator' ) ) {
$args = array( 'post_type' => 'post', 'post_status' => 'publish, pending, 
draft' );
} else {
$args = array( 'post_type' => 'post', 'post_status' => 'publish' );
}
$wp_query = new WP_Query($args); while ( have_posts() ) : the_post(); ?>
CONTENT
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>

This should work for regular WP posts (although I haven’t tested it) but I’m not sure how to apply to Woocommerce. My best guess is:

<?php 
if ( current_user_can(! 'administrator' ) ) {
$args = array( 'post_type' => 'shop_order', 'order_status' => 'complete,failed' );
} else {
$args = array( 'post_type' => 'shop_order', 'post_status' => 'pending-payment,processing' );
}
$wp_query = new WP_Query($args); while ( have_posts() ) : the_post(); ?>
CONTENT
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>

But I’m getting all sorts of errors with this! I’m also not sure if it would only apply to the edit order screen and not the admin shop order table bulk actions dropdown.

Any help would be really appreciated!

Answers:

The conditional function current_user_can() is not recommended with user roles:

While checking against particular roles in place of a capability is supported in part, this practice is discouraged as it may produce unreliable results.

Instead you can get the current user and his roles (as a user can have many).
Also the orders post status are very specific in woocommerce (they all begin by wc- and they should be in an array if many).

So the correct code should be:

<?php 
    // get current user roles (if logged in)
    if( is_user_logged_in() ){
        $user = wp_get_current_user();
        $user_roles = $user->roles;
    } else $user_roles = array();

    // GET Orders statuses depending on user roles
    if ( in_array( 'shop_manager', $user_roles ) ) { // For "Shop Managers"
        $statuses = array( 'wc-pending','wc-processing' );
    } elseif ( in_array( 'administrator', $user_roles ) ) { // For admins (all statuses)
        $statuses = array_keys(wc_get_order_statuses());
    } else 
        $statuses = array();

    $loop = new WP_Query( array(
        'post_type'      => 'shop_order',
        'posts_per_page' => -1,
        'post_status'    => $statuses
    ) );

    if ( $loop->have_posts() ):
    while ( $loop->have_posts() ):
    $loop->the_post();
?>

<?php echo $loop->post->ID .', '; // Outputting Orders Ids (just for test) ?>

<?php
    endwhile;
    endif;
    wp_reset_postdata();
?>

Tested and works