Calculate different order status count and total cash for each order status in Woocommerce

I need to get the order total of a different status in between some days in woocommerce query. For it to loop through all orders in between some day I use the following query:

$args = array(
    'post_type'         => 'shop_order',
    'post_status'       => 'publish',
    'posts_per_page' => -1,

    'date_query' => array(
        array(
            'after'     =>  array(
                'year'  => 2016,
                'month' =>01,
                'day'   =>01,
            ),
            'before'    => array(
                'year'  => 2016,
                'month' => 01,
                'day'   =>30,
            ),
            'inclusive' => true,
        ),
    ),

);
$loop=new WP_Query($args);

By using this code I can loop through all the query and get the details correctly.
Now I need to get the details into following format

Read More

wc-shipped : Total order -> 10 total_cash -> 300$
wc- completed :
Totla order -> 34 total_cash -> 4580$
wc-cancelled : Total order ->
12 total_cash -> 100$

How can I get this detail in this format ?

I know how to get wc-shipped : Total order -> 10

For this I use:

$order_status_get[]=$order->post_status;

$order_status_get= array_count_values($order_status_get);
foreach ($order_status_get  as $key => $value) {
  echo $key.'->'.$value;         
}

But I need the price also. For to get price I can use $order_total_array[]=$order->get_total();

But i don’t know how to combine them and get the result in the desired format.

Related posts

3 comments

  1. The easiest way I know…

    using the WC_Admin_Report class… you can get the result array and manipulate it as you want… sample result is printed below…

    include_once( WP_PLUGIN_DIR . '/woocommerce/includes/admin/reports/class-wc-admin-report.php');
    
    $reports = new WC_Admin_Report();
    $args = array(
        'data' => array(
            '_order_total' => array(
                'type'     => 'meta',
                'function' => 'SUM',
                'name'     => 'total_cash'
            ),
            'ID' => array(
                'type'     => 'post_data',
                'function' => 'COUNT',
                'name'     => 'total_orders'
            ),
            'post_status' => array(
                'type'     => 'post_data',
                'function' => '',
                'name'     => 'status'
            ),
        ),
        'where' => array(
            array(
                'key'      => 'post_date',
                'value'    => date( 'Y-m-d', strtotime( '02/01/2016' ) ), // starting date
                'operator' => '>'
            ),
            array(
                'key'      => 'post_date',
                'value'    => date( 'Y-m-d', strtotime( '02/31/2016' ) ), // end date...
                'operator' => '<'
            ),
        ),
        'where_meta' => array(
            array(
                'meta_key'   => 'who',
                'meta_value' => 'manik',
                'operator'   => '='
            )
        ),
        'order_status' => array( 'cancelled', 'completed', 'shipped' ),
        'group_by'     => 'posts.post_status',
        'query_type'   => 'get_results',
    );
    $data = $reports->get_order_report_data($args);
    print_r($data);
    

    print something like

    Array
    (
        [0] => stdClass Object
            (
                [total_cash] => 35
                [total_orders] => 2
                [status] => wc-cancelled
            )
    
        [1] => stdClass Object
            (
                [total_cash] => 315
                [total_orders] => 21
                [status] => wc-completed
            )
    
        [2] => stdClass Object
            (
                [total_cash] => 211
                [total_orders] => 11
                [status] => wc-shipped
            )
    
    )
    

    then manipulate $data

    //print_r($data);
    // 
    $currency = (function_exists('get_woocommerce_currency_symbol'))?get_woocommerce_currency_symbol():'';
    foreach($data as $item) {
        echo sprintf('<p>%s : Total Orders %s -> Total Cash -> %s%s </p>', $item->status, $item->total_orders, $item->total_cash, $currency);
    }
    

    demo of $data. Click Execute code button.

    Prints like:

    wc-cancelled : Total Orders 2 -> Total Cash -> 35$
    wc-completed : Total Orders 21 -> Total Cash -> 315$
    wc-shipped : Total Orders 11 -> Total Cash -> 211$

  2. I will give a solution that based on your question .

    $order = new WC_Order('your order id ');
    

    In your case

    while($loop->have_posts()): $loop->the_post(); 
      $order_id=get_the_ID();
      $order = new WC_Order($order_id);
    

    (1) get order status from order we can use $order->post_status

    (2) to get order total we can use $order->get_total()

    You can combine them and store it in to one array

     $order_status_array[]=$order->post_status .'*'.$order->get_total();
    

    here i combined using * , you can use your own.

    so that the out put array like

    Array ( [0] => wc-cancelled*64 [1] => wc-cancelled*254 [2] =>wc-cancelled*93 [3] => wc-cancelled*44 [4] => wc-cancelled*213 [5] => wc-cancelled*44)

    Then use the following code to arrange this array in proper format

    $new_array = [];
    
    foreach($order_status_array as $key => $value) {
        list($name, $val) = explode('*', $value);
        if(array_key_exists($name, $new_array)) {
              $new_array[$name]['total_cash'] += $val;
              $new_array[$name]['total_order']++;
        } else {
              $new_array[$name]['total_cash'] = $val;
              $new_array[$name]['total_order'] = 1;
        }
    }
    

    now your array is ready , and it’s like

    Array(
        [wc-cancelled] => Array(
                [total_cash] => ...
                [total_order] =>...
            )
       ...
    )
    

    now use the following code

     foreach ($new_array as $l=>$m){
    echo $l.'Total Order:->'.$m['total_order'] .'Total Cash:->'.$m['total_cash'].'</br>';
    }
    

    . This will work . You can use other good solutions also . Try this .

    so entire code is

     while($loop->have_posts()): $loop->the_post(); 
          $order_id=get_the_ID();
          $order = new WC_Order($order_id);
          $order_status_array[]=$order->post_status .'*'.$order->get_total();
     endwhile;
    
        $new_array = [];
        foreach($order_status_array as $key => $value) {
            list($name, $val) = explode('*', $value);
            if(array_key_exists($name, $new_array)) {
                  $new_array[$name]['total_cash'] += $val;
                  $new_array[$name]['total_order']++;
            } else {
                  $new_array[$name]['total_cash'] = $val;
                  $new_array[$name]['total_order'] = 1;
            }
        }
    
       foreach ($new_array as $l=>$m){
    
        echo $l.'Total Order:->'.$m['total_order'] .'Total Cash:->'.$m['total_cash'].'</br>';
    }
    
  3. If I understand your question correctly, you want all orders dumbed down to a list of rows summed by the post_status field, right?

    In the end you want something like this:

    $order_status = array(
       'wc-shipped' => 10,
       'wc-completed' => 20,
       'wc-cancelled' => 30
    );
    

    I see two options:

    1) Change the query to utilize posts_groupby to only return summarized columns.

    2) Iterate over all the rows in the result set and summarize them by post_status manually. Use an array with the key of the status and increment the value by $order->get_total()

Comments are closed.