Reputation: 23
I would like to assign orders with specific product tags to a specific store manager in the backend and hide the rest of the orders.
I am currently using Order Splitter for WooCommerce free plugin to split orders into separate orders by item (product).
I came across this really good solution to filter order using the product types instead: Filter orders by product post type in WooCommerce admin orders list page and I tried to edit it to show only a specific product tags, however, with no luck. What am I doing wrong?
The product tag is called "brand1" and the shop manager account ID is 7.
add_action( 'restrict_manage_posts', 'admin_shop_order_by_product_type_filter' );
function admin_shop_order_by_product_type_filter(){
global $pagenow, $post_type;
$whoisin = get_current_user_id();
if( 'shop_order' === $post_type && 'edit.php' === $pagenow && ($whoisin == 7) ) {
$domain = 'woocommerce';
$filter_id = 'brand1';
$current = isset($_GET[$filter_id])? $_GET[$filter_id] : '';
$query_args = ['taxonomy' => 'product_tag', 'fields' => 'names', 'orderby' => 'order'];
echo '<select name="'.$filter_id.'">
<option value="">' . __('Filter by Product Tag', $domain) . '</option>';
foreach ( get_terms($query_args) as $term_name ) {
printf( '<option value="%s"%s>%s</option>', $term_name,
$term_name === $current ? '" selected="selected"' : '', ucfirst($term_name) );
}
echo '</select>';
}
}
add_action( 'pre_get_posts','process_admin_shop_order_product_type_filter' );
function process_admin_shop_order_product_type_filter( $query ) {
global $pagenow, $post_type, $wpdb;
$filter_id = 'brand1';
$whoisin = get_current_user_id();
if ( $query->is_admin && 'edit.php' === $pagenow && 'shop_order' === $post_type
&& isset( $_GET[$filter_id] ) && $_GET[$filter_id] != '' && ($whoisin == 7)) {
$order_ids = $wpdb->get_col( "
SELECT DISTINCT o.ID
FROM {$wpdb->prefix}posts o
INNER JOIN {$wpdb->prefix}woocommerce_order_items oi
ON oi.order_id = o.ID
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim
ON oi.order_item_id = oim.order_item_id
INNER JOIN {$wpdb->prefix}term_relationships tr
ON oim.meta_value = tr.object_id
INNER JOIN {$wpdb->prefix}term_taxonomy tt
ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN {$wpdb->prefix}terms t
ON tt.term_id = t.term_id
WHERE o.post_type = '$post_type'
AND oim.meta_key = '_product_id'
AND tt.taxonomy = 'product_tag'
AND t.name = '{$_GET[$filter_id]}'
");
$query->set( 'post__in', $order_ids ); // Set the new "meta query"
$query->set( 'posts_per_page', 25 ); // Set "posts per page"
$query->set( 'paged', ( get_query_var('paged') ? get_query_var('paged') : 1 ) ); // Set "paged"
}
}
Upvotes: 2
Views: 2380
Reputation: 253939
The following altered code will display orders based on the related product tag that are assigned to a shop manager (user ID).
In the first function you will do your product tag assignments by shop manager (user ID). Then orders will be filtered differently for each shop manager, displaying only their assigned orders. Only the defined user Ids will have filtered orders.
The code:
// Settings function
function orders_by_shop_manager_settings(){// Your settings below
// Your settings below
return array(
// Terms field type (can be 'name', 'slug' or 'term_id')
'field' => 'slug',
// The taxonomy for product tags (brands)
'taxonomy' => 'product_tag',
// Manager ID / product tags terms pairs (set the correct term field type as defined before)
'assignments' => array(
'7' => array('brand1','brand7', 'brand9'),
'12' => array('brand3','brand5', 'brand6', 'brand8'),
'189' => array('brand2','brand4'),
)
);
}
// Filtering orders by shop manager based on items product tag(s)
add_action( 'pre_get_posts','filter_orders_by_shop_manager' );
function filter_orders_by_shop_manager( $query ) {
global $pagenow, $typenow, $wpdb;
if ( $query->is_admin && 'edit.php' === $pagenow && 'shop_order' === $typenow ) {
// Loading settings data
$data = orders_by_shop_manager_settings();
$user_id = get_current_user_id();
}
if( isset($data) && isset($data['assignments'][$user_id]) ) {
$taxonomy = $data['taxonomy'];
$field = $data['field'];
$terms = $data['assignments'][$user_id];
$order_ids = $wpdb->get_col( "
SELECT DISTINCT o.ID
FROM {$wpdb->prefix}posts o
INNER JOIN {$wpdb->prefix}woocommerce_order_items oi
ON oi.order_id = o.ID
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta oim
ON oi.order_item_id = oim.order_item_id
INNER JOIN {$wpdb->prefix}term_relationships tr
ON oim.meta_value = tr.object_id
INNER JOIN {$wpdb->prefix}term_taxonomy tt
ON tr.term_taxonomy_id = tt.term_taxonomy_id
INNER JOIN {$wpdb->prefix}terms t
ON tt.term_id = t.term_id
WHERE o.post_type = '$typenow'
AND oim.meta_key IN ( '_product_id','_variation_id' )
AND tt.taxonomy = '$taxonomy'
AND t.$field IN ( '" . implode( "','", $terms ) . "' )
");
if ( count($order_ids) > 0 ) {
$query->set( 'post__in', $order_ids ); // Set the new "meta query"
$query->set( 'posts_per_page', 25 );
} else {
$query->set( 'author__in', 99999999 );
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and Works.
Upvotes: 1