1

For every coupon I have defined in the system I would like to show usage statistics: how much sales it was used with, how much discount it provided, etc... I would like to add that data on that coupon's edit page in the admin (either as a new tab or a metabox)

So I have the code to count all sales used that coupon. But how do I add it to the coupon edit page in woocommerce admin

function get_sales_by_coupon($coupon_id) {

    $args = [
        'post_type' => 'shop_order',
        'posts_per_page' => '-1',
        'post_status' => ['wc-processing', 'wc-completed']
    ];
    $my_query = new WP_Query($args);
    $orders = $my_query->posts;

    $total = 0;

    foreach ($orders as $key => $value) {

        $order_id = $value->ID;
        $order = wc_get_order($order_id);
        $items = $order->get_items('coupon'); 

        foreach ( $items as $item ) {

            if( $item['code'] == $coupon_id ) {
                $total += $order->get_total();
            }
        }
    }
    return 'Total sales for coupon "' . $coupon_id . '": ' . wc_price($total);
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Louis Shraga
  • 773
  • 1
  • 7
  • 26

1 Answers1

4

The more orders you will get, more your function is going to be heavy… Instead it will be much better to make a direct lighter SQL query that will get the sum of orders totals for a defined coupon code.

Then using a custom side metabox on coupon edit pages, you will be able to display that:

// Get totals orders sum for a coupon code
function get_total_sales_by_coupon( $coupon_code ) {
    global $wpdb;

    return (float) $wpdb->get_var( $wpdb->prepare("
        SELECT SUM( pm.meta_value )
        FROM {$wpdb->prefix}postmeta pm
        INNER JOIN {$wpdb->prefix}posts p
            ON pm.post_id = p.ID
        INNER JOIN {$wpdb->prefix}woocommerce_order_items woi
            ON woi.order_id = pm.post_id
        WHERE pm.meta_key = '_order_total'
        AND p.post_status IN ('wc-processing','wc-completed')
        AND woi.order_item_name LIKE '%s'
        AND woi.order_item_type = 'coupon'
    ", $coupon_code ) );
}

// Adding Meta container to admin shop_coupon pages
add_action( 'add_meta_boxes', 'add_custom_coupon_meta_box' );
if ( ! function_exists( 'add_custom_coupon_meta_box' ) )
{
    function add_custom_coupon_meta_box()
    {
        add_meta_box( 'coupon_usage_data', __('Usage data','woocommerce'), 'custom_coupon_meta_box_content', 'shop_coupon', 'side', 'core' );
    }
}

// Displaying content in the meta container on admin shop_coupon pages
if ( ! function_exists( 'custom_coupon_meta_box_content' ) )
{
    function custom_coupon_meta_box_content() {
        global $post;

        $total = get_total_sales_by_coupon( $post->post_title );

        printf( __("Total sales: %s"), wc_price( $total ) );

    }
}

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

enter image description here

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Thanks, Loic, +1 for the resulting screenshot :) – Louis Shraga Sep 23 '19 at 17:54
  • One more question : _order_total gives me including shipping. I cant find how to get subtotal - will _order_subtotal work ? – Louis Shraga Sep 24 '19 at 09:51
  • @LouisShraga for an order the available totals meta keys are: `_cart_discount`, `_cart_discount_tax`, `_order_shipping`, `_order_shipping_tax`, `_order_tax` and `_order_total`… There is no subtotal. This needs to be calculated from order items meta data or from order totals meta data… So it's going to be complicated… It should be better, when an order is created, to add a custom field (custom meta data) with the **required subtotal** (for each order), to avoid complicated queries and calculations. – LoicTheAztec Sep 24 '19 at 11:18