I used this solution to filter users product list, now I'm looking for a solution to filter the orders list of WooCommerce in admin dashboard. That means, a logged-in user can only see the orders for products which he/she published, and can not see orders for other managers products.
I tried this code, with help of ChatGPT but didn't work:
// Filter orders by products authored by the logged-in user in admin
function filter_orders_by_author_in_admin($query) {
global $pagenow, $post_type;
// Check if it's the orders page in admin and the user is not an administrator
if (is_admin() && $pagenow == 'edit.php' && $post_type == 'shop_order' && !current_user_can('administrator')) {
// Get current user ID
$current_user_id = get_current_user_id();
// Get products authored by the current user
$args = array(
'post_type' => 'product',
'author' => $current_user_id,
'posts_per_page' => -1, // Get all products authored by the user
);
$products_query = new WP_Query($args);
// Extract product IDs
$product_ids = wp_list_pluck($products_query->posts, 'ID');
// Modify the query to only include orders related to products authored by the current user
$meta_query = array(
array(
'key' => '_product_id',
'value' => $product_ids,
'compare' => 'IN',
),
);
// Combine with existing meta queries, if any
$meta_query_combined = $query->get('meta_query');
$meta_query_combined[] = $meta_query;
$query->set('meta_query', $meta_query_combined);
}
}
add_action('pre_get_posts', 'filter_orders_by_author_in_admin');
How can I achieve that?
The following will display orders based on the product author, the following will display related orders only for the author, in admin orders list
It restricts orders filtering to "event_manager" user role.
1). For legacy "shop_order" posts:
// Conditional function: Check if user has specific user role
function has_targeted_user_role( $targeted_role = 'event_manager' ) {
global $current_user;
return in_array($targeted_role, $current_user->roles);
}
// Custom function to get orders IDs from product author
function get_orders_by_product_author( $user_id ) {
global $wpdb;
return $wpdb->get_col("
SELECT DISTINCT o.order_id
FROM {$wpdb->prefix}wc_order_product_lookup o
LEFT JOIN {$wpdb->prefix}posts p
ON o.product_id = p.ID
WHERE p.post_author = '{$user_id}'
" );
}
// For classic shop_order posts (doesn't work with High-Performance Order Storage)
add_action( 'pre_get_posts', 'filter_shop_order_posts_by_product_author' );
function filter_shop_order_posts_by_product_author( $query ) {
global $pagenow, $post_type;
if ( is_admin() && has_targeted_user_role() && 'edit.php' === $pagenow && 'shop_order' === $post_type ) {
$query->set('post__in', get_orders_by_product_author( get_current_user_id() ) );
}
}
2). For High-Performance Order Storage (HPOS):
When HPOS is enabled, the only way to restrict/filter orders, is to add the product author as custom order metadata on new orders to filter them.
// Conditional function: Check if user has specific user role
function has_targeted_user_role( $targeted_role = 'event_manager' ) {
global $current_user;
return in_array($targeted_role, $current_user->roles);
}
// Add product author metadata when placing a new order
add_action( 'woocommerce_checkout_create_order', 'wc_checkout_create_order_callback', 10, 2 );
function wc_checkout_create_order_callback( $order, $data ) {
// Loop though cart items
foreach( WC()->cart->get_cart() as $item ) {
if ( $author_id = get_post_field( 'post_author', $item['product_id'] ) ) {
$order->add_meta_data('_product_author_id', $author_id );
}
}
}
// Add product author metadata on status changed if not yet set
add_action( 'woocommerce_order_status_changed', 'woocommerce_order_status_changed_callback', 10, 4 );
function woocommerce_order_status_changed_callback( $order_id, $old_status, $new_status, $order ) {
if ( ! $order->get_meta('_product_author_id') ) {
$save = false; // Initializing
// Loop though cart items
foreach( $order->get_items() as $item ) {
if ( $author_id = get_post_field( 'post_author', $item['product_id'] ) ) {
$order->add_meta_data('_product_author_id', $author_id );
$save = true;
}
}
if ( $save ) $order->save();
}
}
// Filter order by specific metadata and user role (HPOS)
add_filter( 'woocommerce_order_query_args', 'filter_wc_order_by_product_author' );
function filter_wc_order_by_product_author( $query_args ) {
if ( is_admin() && has_targeted_user_role() && isset($_GET['page'])
&& $_GET['page'] === 'wc-orders' ) {
$query_args['meta_query'][] = array(
'key' => '_product_author_id',
'value' => get_current_user_id(),
);
}
return $query_args;
}
Code goes in functions.php file of your child theme (or in a plugin). Tested and works.