1

I need to sort fees by name rather than the default by price in WooCommerce orders.

Using Reordering multiple fees differently in Woocommerce cart and checkout pages answer code, I have managed to sort fees by name in cart and checkout pages. But it doesn't work for the order confirmation and emails that get sent out.

Thank you for your help.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Harry Fox
  • 13
  • 2

1 Answers1

0

Updated

To sort fees by name on customer orders and email notifications, you will use the following:

// Custom function that sort displayed fees by name on order items
function wc_get_sorted_order_item_totals_fee_rows( &$total_rows, $tax_display, $order ) {
    $fees = $order->get_fees();

    if ( $fees ) {
        $fee_names = []; // initializing

        // First Loop
        foreach ( $fees as $fee_id => $fee ) {
            $fee_names[$fee_id] = $fee->get_name();
        }
        asort($fee_names); // Sorting by name

        // 2nd Loop
        foreach ( $fee_names as $fee_id => $fee_name ) {
            $fee = $fees[$fee_id];

            if ( apply_filters( 'woocommerce_get_order_item_totals_excl_free_fees', empty( $fee['line_total'] ) && empty( $fee['line_tax'] ), $fee_id ) ) {
                continue;
            }

            $total_rows[ 'fee_' . $fee->get_id() ] = array(
                'label' => $fee->get_name() . ':',
                'value' => wc_price( 'excl' === $tax_display ? $fee->get_total() : $fee->get_total() + $fee->get_total_tax(), array( 'currency' => $order->get_currency() ) ),
            );
        }
    }
}

// Display sorted fees by name everywhere on orders and emails
add_filter( 'woocommerce_get_order_item_totals', 'display_date_custom_field_value_on_order_item_totals', 10, 3 );
function display_date_custom_field_value_on_order_item_totals( $total_rows, $order, $tax_display ){
    // Initializing variables
    $new_total_rows = $item_fees = [];

    // 1st Loop - Check for fees
    foreach ( $total_rows as $key => $values ) {
        if( strpos($key, 'fee_') !== false ) {
            $item_fees[] = $key;
        }
    }

    if( count($item_fees) > 1 ) {
        // 2nd Loop - Remove item fees total lines
        foreach ( $item_fees as $key ) {
            unset($total_rows[$key]);
        }

        $key_start = isset($total_rows['shipping']) ? 'shipping' : ( isset($total_rows['discount']) ? 'discount' : 'cart_subtotal' );

        // 3rd Loop - loop through order total rows
        foreach( $total_rows as $key => $values ) {
            $new_total_rows[$key] = $values;

            // Re-inserting sorted fees
            if( $key === $key_start ) {
                wc_get_sorted_order_item_totals_fee_rows( $new_total_rows, $tax_display, $order );
            }
        }
        return $new_total_rows;
    }
    return $total_rows;
}

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

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Thanks for this, but its still not working. Where about would I edit this to change the order from highest price to lowest price first or vice versa? Thank you for your help – Harry Fox Aug 17 '20 at 14:04
  • Sorry but it works perfectly on last woocommerce version under Storefront theme… I remember that you asked in your question to sort fees by name, so why do you want now to sort them by price? – LoicTheAztec Aug 17 '20 at 14:17
  • I will try it in a different theme. Its becuase the customer wants both options , sort by name and sort by price (lowest first). Sorry I should of mentioned it in my question. – Harry Fox Aug 17 '20 at 14:20
  • @HarryFox Is simply not possible as it's not an SQL query… so you sort them by name or you do it by cost, but both no. – LoicTheAztec Aug 17 '20 at 14:24
  • Ok can you show me how to do it by cost lowest first? I think that would be a better option for the customer. Thank you for all your help on this. – Harry Fox Aug 17 '20 at 14:26