Search code examples
phpwordpresswoocommercehook-woocommerceorders

Process multiple Custom bulk action on Woocommerce admin Orders list


In WooCommerce using the plugin Admin Custom Order Fields, I have a added a custom fields "Rebates Status" with 3 values "No Rebates", "Unpaid" and "Paid", on WooCommerce admin Orders list.

enter image description here

I have also displayed that on the view order screen just like the screenshot below:

enter image description here

Now I would like to bulk update the Rebates Status on selected orders, just as wooCommerce allow to do it for orders status bulk change.

Based on "Process custom bulk action on admin Orders list in Woocommerce" answer thread, I successfully added the 3 Rebates statuses on the bulk edit dropdown (as you can see on the first screenshot):

add_filter( 'bulk_actions-edit-shop_order', 'decrease_meals_orders_bulk_actions' );
function decrease_meals_orders_bulk_actions( $bulk_actions ) {
    $bulk_actions['mr_norebates'] = 'Mark Transactions as No Rebates';
    $bulk_actions['mr_unpaid'] = 'Mark Transactions as Unpaid';
    $bulk_actions['mr_paid'] = 'Mark Transactions as Paid';
    return $bulk_actions;
}

But no changes are applied when I try to bulk update the Rebates status for selected orders.

The meta key for Rebates Status is _wc_acof_2

Im stuck also and don't know how to solve the problem.

Any help is appreciated.


Solution

  • This is the complete, compact and optimized way to make it work for each of the 3 actions, to bulk update your custom "Rebate status" displaying a summary notice:

    // Your settings in a function
    function custom_admin_orders_bulk_actions( $labels = false ){
        $domain = 'woocommerce';
        return array(
            'mr_norebates'  => $labels ? __('No Rebates', $domain) : 'norebates',
            'mr_unpaid'     => $labels ? __('Unpaid', $domain)     : 'unpaid',
            'mr_paid'       => $labels ? __('Paid', $domain)       : 'paid',
        );
    }
    
    // Display the custom actions on admin Orders bulk action dropdown
    add_filter( 'bulk_actions-edit-shop_order', 'set_transactions_orders_bulk_actions' );
    function set_transactions_orders_bulk_actions( $bulk_actions ) {
        foreach( custom_admin_orders_bulk_actions(true) as $key => $label ) {
            $bulk_actions[$key] = sprintf( __('Mark Transactions as %s', 'woocommerce'), $label );
        }
        return $bulk_actions;
    }
    
    // Process the bulk action from selected orders
    add_filter( 'handle_bulk_actions-edit-shop_order', 'set_transactions_bulk_action_edit_shop_order', 10, 3 );
    function set_transactions_bulk_action_edit_shop_order( $redirect_to, $action, $post_ids ) {
        $actions = custom_admin_orders_bulk_actions();
    
        if ( in_array( $action, array_keys($actions) ) ) {
            $processed_ids = array(); // Initializing
    
            foreach ( $post_ids as $post_id ) {
                // Save the new value
                update_post_meta( $post_id, '_wc_acof_2', $actions[$action] );
    
                $processed_ids[] = $post_id; // Adding processed order IDs to an array
            }
    
            // Adding the right query vars to the returned URL
            $redirect_to = add_query_arg( array(
                'rebate_action'   => $action,
                'processed_count' => count( $processed_ids ),
                'processed_ids'   => implode( ',', $processed_ids ),
            ), $redirect_to );
        }
        return $redirect_to;
    }
    
    // Display the results notice from bulk action on orders
    add_action( 'admin_notices', 'set_transactions_bulk_action_admin_notice' );
    function set_transactions_bulk_action_admin_notice() {
        global $pagenow;
    
        if ( 'edit.php' === $pagenow && isset($_GET['post_type']) && 'shop_order' === $_GET['post_type']
        && isset($_GET['rebate_action']) && isset($_GET['processed_count']) && isset($_GET['processed_ids']) ) {
    
            foreach( custom_admin_orders_bulk_actions(true) as $key => $label ) {
                if (  $_GET['rebate_action'] === $key ) {
    
                    $count = intval( $_GET['processed_count'] );
    
                    printf( '<div class="notice notice-success fade is-dismissible"><p>' .
                        _n( '%s selected order updated to "%s" rebate status.',
                        '%s selected orders updated to "%s" rebate status.',
                        $count, 'woocommerce' )
                     . '</p></div>', $count, $label );
                }
            }
        }
    }
    

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

    Based on: Process custom bulk action on admin Orders list in Woocommerce