Search code examples
phpwordpresswoocommercehook-woocommerceorders

Add order total weight to WooCommerce admin orders list (HPOS compatible)


I used to use a plugin to add the total order weight to each order and display it on the orders page on the back end. However, HPOS broke this and I have been trying to write the code to implement it again. I have Frankensteined a few snippets I have found, as my PHP skills are very limited, and this is as far as I have gotten, I just can't seem to get it to populate the values.

I know a lot of you will look at this and say to yourself, what an idiot, but hopefully, someone might be able to point me in the right direction

add_filter( 'manage_woocommerce_page_wc-orders_columns', 'add_order_weight_column' );
function add_order_weight_column( $columns ) {
       $columns['total_weight'] = __( 'Weight', 'woocommerce' );
    return $columns;
}

add_action( 'manage_shop_order_posts_custom_column', 'populate_order_weight_column_content', 10, 2 );
function populate_order_weight_column_content( $column ) {
     if ( $column == 'total_weight' ) {
        global $the_order;

        $total_weight = $the_order->get_meta('_cart_weight');

        if ( $total_weight > 0 ) {
            echo wc_format_weight( $total_weight );
        } else {
            _e('N/A', 'woocommerce');
        }
    }
}

The column doesn't need to be sortable, I just need the total weight to be displayed


Solution

  • The main issue in your code is that you are not using the right hook on your 2nd function, when HPOS is enabled, so nothing is displayed in your custom column.

    Make sure that "_cart_weight" is the correct meta key used to register the total weight (see the addition below for compatibility issue).

    The following will work with or without HPOS enabled:

    add_filter( 'manage_woocommerce_page_wc-orders_columns', 'add_custom_columns_to_admin_orders', 20); // HPOS
    add_filter( 'manage_edit-shop_order_columns', 'add_custom_columns_to_admin_orders', 20);
    function add_custom_columns_to_admin_orders( $columns ) {
        return array_merge( $columns, ['total_weight' => __( 'Weight', 'woocommerce' )] );
    }
    
    add_action('manage_woocommerce_page_wc-orders_custom_column', 'custom_columns_content_in_admin_orders', 10, 2); // HPOS
    add_action( 'manage_shop_order_posts_custom_column', 'custom_columns_content_in_admin_orders', 10, 2);
    function custom_columns_content_in_admin_orders( $column, $order ) {
        if( ! is_a($order, 'WC_order') && $order > 0 ) {
            $order = wc_get_order( $order );
        }
    
        if ( 'total_weight' === $column ) {
            $total_weight = $order->get_meta('_cart_weight');
            echo $total_weight > 0 ? wc_format_weight($total_weight) : __('N/A', 'woocommerce');
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin).


    Addition

    If registered total weight is not compatible with HPOS, that means that the code used to register the total weight is using WordPress post meta function instead of using the required WooCommerce setter method compatible with HPOS.

    Solution:

    1. Replace the code that register the total weight with:
    add_action('woocommerce_checkout_create_order', 'add_checkout_order_total_weight', 100);
    function add_checkout_order_total_weight( $order ) {
        $order->update_meta_data('_cart_weight', WC()->cart->get_cart_contents_weight());
    }
    

    Make sure to remove the old code (or the related 3rd party plugin functionality).


    1. Add total weight on manual orders or recalculate total weight on admin orders:
    add_action( 'woocommerce_process_shop_order_meta', 'add_edit_admin_order_total_weight', 60 );
    function add_edit_admin_order_total_weight( $order_id ) {
        $order = wc_get_order($order_id); // Get WC_Order instance
        $total_weight = 0; // Initializing
        
        // Loop through order items
        foreach ( $order->get_items() as $item ) {
            $product  = $item->get_product(); // Get WC_Product instance
            $weight = (float) $product->get_weight(); // Get product weight
    
            $total_weight += $weight > 0 ? $item->get_quantity() * $weight : 0; // Increase total weight
        }
    
        $initial_total_weight = (float) $order->get_meta('_cart_weight'); // Check initial
    
        if ( $initial_total_weight !== $total_weight ) {
            $order->update_meta_data('_cart_weight', WC()->cart->get_cart_contents_weight());
            $order->save();
        }
    }
    

    1. Synchronize previous orders (optional):

    How to run WooCommerce HPOS sync again for previously synced orders?


    Related: