CreateIT
CreateIT
BLOG

WooCommerce orders report sent by e-mail

WooCommerce
TAGS: WooCommerce

WooCommerce orders report sent by e-mail

SHARE

Challenge:
generate a table list of recent shop orders
Solution:
configure a cron job to send a morning report with an order list

Nowadays, a lot of businesses sell things online. The key to an efficient online shopping experience is automation. WooCommerce, the most popular ecommerce solution, offers multiple integrations with third-party platforms: payments, invoicing systems or CRM. In most cases, the entire order list / reports / payment statuses are available via the Administrator Backend Panel. However, sometimes there is a need to generate an order report and to send it to the accountant’s e-mail. We can use WP Cron to achieve this.

WooCommerce internal API call

We will be using the WP_REST_Request() method to call Woo API version 3. We’re looking for orders that were created yesterday ( yesterday 00:00 – yesterday 23:59 ). Endpoint ‘/wc/v3/orders’ expects a date to be formatted in the ISO8601 format. WordPress Cron is running out of wp_user context, so we have to authenticate the user with the “administrator” role by triggering the wp_set_current_user() function. Only then will the internal WordPress API Call fetch proper data.

Cron event

The cron event will be scheduled to execute daily after 6.00 AM. The HTML Table with a summary, and basic order information will be sent by e-mail to the accountant or administrator. For better presentation, the tables have every other row colored.

WooCommerce email report

This PHP script can be used to create other reports. Just use a different WooCommerce API endpoint and fetch the needed data: about customers / products / refunds or stocks. Here is a cron event job that will generate the list of all WooCommerce orders from yesterday.

// functions.php
/**
 * Orders stats report
 */
add_action('ct_cron_yesterday_orders3', 'ct_report_orders');

add_action('init', 'schedule_cron3');

function schedule_cron3(){
    if( !wp_next_scheduled( 'ct_cron_yesterday_orders3' ) ) {
        wp_schedule_event( strtotime('06:00:00'), 'daily', 'ct_cron_yesterday_orders3' );
    }
}

function ct_report_orders(){

    ct_cron_authenticate_user();

    // yesterday range
    $date1 = strtotime('yesterday -30days 00:00');
    $date2 = strtotime('yesterday 23:59');
    // converting Unix time to DateTime (ignoring timezones)
    $date1_datetime = new DateTime('@' .$date1);
    $date2_datetime = new DateTime('@' .$date2);
    $date1_ISO8601 = $date1_datetime->format(DateTime::ATOM);
    $date2_ISO8601 = $date2_datetime->format(DateTime::ATOM);
    // internal API call
    $request = new WP_REST_Request( 'GET', '/wc/v3/orders' );
    $request->set_query_params( [ 'status' => 'any', 'before' => $date2_ISO8601, 'after' => $date1_ISO8601 ] );
    $response = rest_do_request( $request );
    $server = rest_get_server();
    $data = $server->response_to_data( $response, false );
    if(isset($data['code'])){
        return new WP_REST_Response( $data, 401 );
    }
    $body = '';
    if(!empty($data)):
        // prepare email
        $body = '<table cellpadding="0" cellspacing="0" width="640" align="left" border="1" bordercolor="#ccc">';
        $body .= '<tr><td style="padding:10px; background:#000; color:#ccc;">';
        $body .= '<p>'. count($data) .' Orders from: '. $date1_datetime->format('Y-m-d') . '</p>';
        $body .= '</td></tr>';
        $row_count = 1;
        foreach($data as $row){
            $row_style = 'style="background: #fff; padding:10px;"';
            if($row_count % 2 == 0){
                $row_style = 'style="background: #f5f5f5; padding:10px;"';
            }
            $body .= '<tr><td ' .$row_style. '>';
            $body .= 'Number: ' . $row['number'] .' -> ';
            $body .= 'Status: ' . $row['status'] .' -> ';
            $body .= 'Date: ' . $row['date_created'] .' -> ';
            $body .= json_encode(maybe_unserialize($row['shipping']));
            $body .= '</td></tr>';
            $row_count++;
        }
        $body .= '</table>';
    endif;
    if(!empty($body)){
        // send email
        $to = get_bloginfo('admin_email');
        $subject = 'Orders Stats : '. get_site_url();
        $headers = array('Content-Type: text/html; charset=UTF-8');
        $res = wp_mail( $to, $subject, $body, $headers );
        var_dump($res);
    }
}
function ct_cron_authenticate_user(){
    if ( defined( 'DOING_CRON' ) ){
        // Notice - CRON job is running out of user context
        // To call internal API endpoint we will - hardcode user_id and authenticate the user
        // user_id = 1 = admin (with administrator privileges)
        wp_set_current_user ( 1 );
    }
}

Testing the cron job

Now we should wait until tomorrow morning to check if our script works. Or – there is a more clever way for testing cron job events – WP CLI provides a way to execute a single job by executing a command in a shell window:

// WP CLI command
wp cron event run ct_cron_yesterday_orders3

Report from last month

We can easily change the range of dates that are used to generate order report. To get a list of orders from the last 30 days, the following 2 lines should be used:

// last 30 days range
$date1 = strtotime('yesterday -30days 00:00');
$date2 = strtotime('yesterday 23:59');

Better WP-Cron

The WordPress built-in Cron mechanism is not perfect, it does not run constantly, but is triggered only on page load. Then, a list of scheduled tasks will be checked and tasks due to run will be executed. As an example, if you scheduled a cron event to run daily after 6.00, but the first visitor will enter any page at 9:15, only then will your event be executed. If you need a more precise time schedule, it’s recommended to disable WP CRON, and set up a cron check in the hosting panel.

// wp-config.php
define('DISABLE_WP_CRON', true);

Then configure CRON in the Linux / Hosting Panel. Cron should run every 5-10 minutes and call the file wp-cron.php. WordPress will check overdue tasks and que them to be executed. Cron configuration depends on the particular Panel version, but the most popular setups are:

// Cron hosting setup
// Option1
cd ${HOME}/public_html; /usr/local/bin/php -q wp-cron.php

// Option2
*/10 * * * *  cd ${HOME}/public_html; /usr/local/bin/php -q wp-cron.php

// Option3
/usr/bin/php /home/USERNAME/public_html/wp-cron.php >/dev/null 2>&1

// Option4
wget -q -O - https://yoursite.com/wp-cron.php >/dev/null 2>&1

That’s it for today’s tutorial. Make sure to follow us for other useful tips and guidelines.

Need help?

  • Looking for support from experienced programmers?

  • Need to fix a bug in the code?

  • Want to customize your webste/application?

ADD COMMENT

Your email address will not be published. Required fields are marked *

createIT Contact