Search code examples
phpwordpresswoocommerceorderscoupon

How to retrieve a list of WooCommerce orders which use a particular coupon?


I'm trying to write a function that retrieves a list of WooCommerce orders which use a specified coupon code and are in a specified date range, then sums the total discounts applied to those orders.

After a little googling I feel like I should be using something like

$customer_orders = get_posts( array(
    'numberposts' => -1,
    'meta_key'    => ???,
    'meta_value'  => $CouponToSearchFor,
    'post_type'   => wc_get_order_types(),
    'post_status' => array_keys( wc_get_order_statuses() ),
) ); 

I've tried:

'meta_key' => 'coupon'
'meta_key' => 'shop_coupon'
'meta_key' => '_coupon'

But none of those work. How can I find out which meta_key/meta_value terms will give me what I need?

Additionally I think meta_query can be used to perform the date filtering as part of this get_posts() query, is that correct?


Solution

  • Your code is not working because by default WooCommerce does't store used coupon code in wp_postmeta table. It stores in wp_woocommerce_order_items table, under order_item_type => coupon and order_item_name => YOUR_CODE.

    You have to first get all the Order ID(s), then you have to loop it to get the desired total, or tax or discount.

    Here is the code:

    function wh_getOrderbyCouponCode($coupon_code, $start_date, $end_date) {
        global $wpdb;
        $return_array = [];
        $total_discount = 0;
    
        $query = "SELECT
            p.ID AS order_id
            FROM
            {$wpdb->prefix}posts AS p
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
            WHERE
            p.post_type = 'shop_order' AND
            p.post_status IN ('" . implode("','", array_keys(wc_get_order_statuses())) . "') AND
            woi.order_item_type = 'coupon' AND
            woi.order_item_name = '" . $coupon_code . "' AND
            DATE(p.post_date) BETWEEN '" . $start_date . "' AND '" . $end_date . "';";
    
        $orders = $wpdb->get_results($query);
    
        if (!empty($orders)) {
            $dp = ( isset($filter['dp']) ? intval($filter['dp']) : 2 );
            //looping throught all the order_id
            foreach ($orders as $key => $order) {
                $order_id = $order->order_id;
                //getting order object
                $objOrder = wc_get_order($order_id);
    
                $return_array[$key]['order_id'] = $order_id;
                $return_array[$key]['total'] = wc_format_decimal($objOrder->get_total(), $dp);
                $return_array[$key]['total_discount'] = wc_format_decimal($objOrder->get_total_discount(), $dp);
                $total_discount += $return_array[$key]['total_discount'];
            }
    //        echo '<pre>';
    //        print_r($return_array);
        }
        $return_array['full_discount'] = $total_discount;
        return $return_array;
    }
    

    Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.

    USAGE

    $orders = wh_getOrderbyCouponCode('my_code', '2016-09-17', '2016-10-07');
    echo 'Total Discount : ' . $orders['full_discount'];
    //print_r($orders);
    

    Please Note:

    All dates are in YYYY-MM-DD format.
    print_r(array_keys(wc_get_order_statuses())); will output something like this:

    Array
    (
        [0] => wc-pending
        [1] => wc-processing
        [4] => wc-on-hold
        [5] => wc-completed
        [6] => wc-cancelled
        [7] => wc-refunded
        [8] => wc-failed
    )
    

    Code is tested and works.

    Hope this helps!