WooCommerce orders report sent by e-mail - Blog | createIT
Get a free advice now!

    Pick the topic
    Developer OutsourcingWeb developingApp developingDigital MarketingeCommerce systemseEntertainment systems

    Thank you for your message. It has been sent.

    WooCommerce orders report sent by e-mail

    October 14, 2021
    Last update: February 13, 2023
    3 min read
    19
    0
    0
    WooCommerce orders report sent by e-mail

    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.

    Technology
    Be on the same page as the rest of the industry.

    Contact us