4

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

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.

Manik
  • 513
  • 1
  • 7
  • 23

3 Answers3

3

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$

Reigel Gallarde
  • 64,198
  • 21
  • 121
  • 139
  • Thank you Reigel . I am going to check this . – Manik Feb 04 '16 at 10:36
  • could you please check this line date( 'Y-m-d', strtotime( '01/01/2016' ) ),'value' => date( 'Y-m-d', strtotime( '02/01/2016' ) ) . You correctly write it or not ? – Manik Feb 04 '16 at 10:45
  • also , how can i check custom field value in this query ?. Because in shop_order post type i have a custom field also . I write this also in wp_query for example 'meta_key' => 'who', 'meta_value' => 'manik' – Manik Feb 04 '16 at 10:48
  • 1
    I updated the code.. `where_meta` is where you can add `meta_key` and `meta_value`. Feel free to change the dates according to your needs. – Reigel Gallarde Feb 04 '16 at 12:48
  • Thank you Reigel , it is working . Only problem is i need to write two quires . – Manik Feb 04 '16 at 12:50
  • why would there be 2? – Reigel Gallarde Feb 04 '16 at 12:51
  • one for my order query to get details , and one for getting report . – Manik Feb 04 '16 at 12:54
  • Hi where from you get this information 'where_meta' ?? . Is that in wordpress codex. Please give the link – Manik Feb 04 '16 at 12:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102599/discussion-between-reigel-and-manik). – Reigel Gallarde Feb 04 '16 at 12:56
  • Hi could you please check this question http://stackoverflow.com/questions/36526268/sql-query-to-download-order-report-in-woocommerce – Manik Apr 10 '16 at 11:05
  • If you can give the solution for that question , it is really helpful . Please check . – Manik Apr 10 '16 at 14:44
3

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>';
}
Sagin
  • 989
  • 8
  • 8
  • Working . This is the same way like my code .Thank you . – Manik Feb 06 '16 at 12:12
  • working good, of course... but not good in terms of code practice... specially if you have hundreds of thousands of orders... this loop is too costly to run... - but yes, it's always you as a programmer to chose which one to go and use.. .. I'm not saying it's not working though... [what's the difference, in terms of display, with this one anyway?](http://sandbox.onlinephpfunctions.com/code/ddae4094d23f3a475959490c10171a9d6ef62bb6) – Reigel Gallarde Feb 07 '16 at 11:18
  • Ok. You may be correct . I am going to accept your answer :) . But really thank you sagin for this solution .It is working i checked the solution . – Manik Feb 07 '16 at 12:30
  • Hi could you please check this question http://stackoverflow.com/questions/36526268/sql-query-to-download-order-report-in-woocommerce – Manik Apr 10 '16 at 11:05
  • 1
    my answer is one way to answer this problem . But @Reigel answer is best . – Sagin Dec 21 '16 at 12:02
1

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()

ZeissS
  • 11,867
  • 4
  • 35
  • 50
  • Thank you friend . But could you please write the entire query , so that i can understand it . It will also help the other people who have same problem . – Manik Feb 04 '16 at 10:03
  • Hi could you please check this question http://stackoverflow.com/questions/36526268/sql-query-to-download-order-report-in-woocommerce – Manik Apr 10 '16 at 11:05