skip to Main Content

By default Woocommerce orders table displays all available order status on the My Account page which is not sortable by customer, therefore I need to have a separate table for every unique order statue (example : ‘on-hold’ ) to display orders table based on only required statue.

I tried this code but it doesn’t output the table:

/* Shortcode To Display Only On-hold Orders On A Custom Page */

add_shortcode('account_on_hold', 'get_customer_orders_on_hold');

function get_customer_orders_on_hold() {


  if( $user = wp_get_current_user() ){

    // Get 'on-hold' customer ORDERS
        $on_hold_orders = wc_get_orders( array(
            'limit' => -1,
            'customer_id' => $user->ID,
            'status' => array('on-hold'),
        ) );

    }
    return $on_hold_orders ;
} 

Related Topic : Get customer “on-hold” order status total amount in Woocommerce

Your advice would be appreciated!

2

Answers


  1. You could use woocommerce table template to generate the html table. You only need to put a conditional check before generating it.

    woocommerce table template
    +
    if("On hold" == esc_html(wc_get_order_status_name($order->get_status())))

    So you could set this up in multiple ways, for example it could be something like this:

    add_shortcode('account_on_hold', 'get_customer_orders_on_hold');
    
    function get_customer_orders_on_hold()
    {
      if ($user = wp_get_current_user()) {
    
      $on_hold_orders = wc_get_orders(array(
        'limit' => -1,
        'customer_id' => $user->ID,
        'status' => array('on-hold'),
      ));
    
      if ($on_hold_orders) :
    ?>
        <table class="woocommerce-orders-table woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table">
          <thead>
            <tr>
              <?php foreach (wc_get_account_orders_columns() as $column_id => $column_name) : ?>
                <th class="woocommerce-orders-table__header woocommerce-orders-table__header-<?php echo esc_attr($column_id); ?>"><span class="nobr"><?php echo esc_html($column_name); ?></span></th>
              <?php endforeach; ?>
            </tr>
          </thead>
    
          <tbody>
            <?php
            foreach ($on_hold_orders as $order) {
              $order      = wc_get_order($order);
              $item_count = $order->get_item_count() - $order->get_item_count_refunded();
              if ("On hold" == esc_html(wc_get_order_status_name($order->get_status()))) :
            ?>
                <tr class="woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr($order->get_status()); ?> order">
                  <?php foreach (wc_get_account_orders_columns() as $column_id => $column_name) : ?>
                    <td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-<?php echo esc_attr($column_id); ?>" data-title="<?php echo esc_attr($column_name); ?>">
                      <?php if (has_action('woocommerce_my_account_my_orders_column_' . $column_id)) : ?>
                        <?php do_action('woocommerce_my_account_my_orders_column_' . $column_id, $order); ?>
    
                      <?php elseif ('order-number' === $column_id) : ?>
                        <a href="<?php echo esc_url($order->get_view_order_url()); ?>">
                          <?php echo esc_html(_x('#', 'hash before order number', 'woocommerce') . $order->get_order_number()); ?>
                        </a>
    
                      <?php elseif ('order-date' === $column_id) : ?>
                        <time datetime="<?php echo esc_attr($order->get_date_created()->date('c')); ?>"><?php echo esc_html(wc_format_datetime($order->get_date_created())); ?></time>
    
                      <?php elseif ('order-status' === $column_id) : ?>
                        <?php echo esc_html(wc_get_order_status_name($order->get_status())); ?>
    
                      <?php elseif ('order-total' === $column_id) : ?>
                        <?php
                        echo wp_kses_post(sprintf(_n('%1$s for %2$s item', '%1$s for %2$s items', $item_count, 'woocommerce'), $order->get_formatted_order_total(), $item_count));
                        ?>
    
                      <?php elseif ('order-actions' === $column_id) : ?>
                        <?php
                        $actions = wc_get_account_orders_actions($order);
    
                        if (!empty($actions)) {
                          foreach ($actions as $key => $action) {
                            echo '<a href="' . esc_url($action['url']) . '" class="woocommerce-button button ' . sanitize_html_class($key) . '">' . esc_html($action['name']) . '</a>';
                          }
                        }
                        ?>
                      <?php endif; ?>
                    </td>
                  <?php endforeach; ?>
                </tr>
            <?php
              endif;
            }
            ?>
          </tbody>
        </table>
    
      <?php endif; ?>
    
    <?php }
    }
    

    Tested and works.

    Login or Signup to reply.
  2. Ruvee’s way is good to customize.
    Alternatively, if you want output just the same as "my-account/orders", there is also the method to call the template.

    add_shortcode('account_on_hold', 'get_customer_orders_on_hold');
    function get_customer_orders_on_hold() {
        if( $user = wp_get_current_user() ){
            $customer_orders = wc_get_orders(
                array(
                    'customer' => $user->ID,
                    'limit' => -1,
                    'page' => 1,
                    'paginate' => true,
                    'status' => array('on-hold'),
                )
            );
            ob_start();
            wc_get_template(
                'myaccount/orders.php',
                array(
                    'current_page'    => 1,
                    'customer_orders' => $customer_orders,
                    'has_orders'      => 0 < $customer_orders->total,
                )
            );
            return ob_get_clean();
        }
    } 
    

    (Addition) The way to add custom menu on the myaccount.

    // Add custom endpoint
    add_action( 'init', function () {
        add_rewrite_endpoint( 'on-hold-orders', EP_ROOT | EP_PAGES );
    });
    
    // Add custom menu
    add_filter( 'woocommerce_account_menu_items', function ( $items ) {
        $new_items = array();
        foreach( $items as $key => $item ){// Loop menu items
            $new_items[$key] = $item;
            if( 'orders' == $key ) $new_items['on-hold-orders'] = __( 'On hold orders' ); 
        }
        return $new_items;
    }, 20 );
    
    // Output custom menu page template
    add_action( 'woocommerce_account_on-hold-orders_endpoint', function( $current_page ) {
        $current_page = empty( $current_page ) ? 1 : absint( $current_page ); // With paginate
        $customer_orders = wc_get_orders( array(
            'customer' => get_current_user_id(),
            'page'     => $current_page,
            'paginate' => true,
            'status' => array('on-hold'),
        ));
        wc_get_template(
            'myaccount/orders.php',
            array(
                'current_page'    => absint( $current_page ),
                'customer_orders' => $customer_orders,
                'has_orders'      => 0 < $customer_orders->total,
            )
        );
    } );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search