report_data ) ) { $this->query_report_data(); } return $this->report_data; } /** * Get all data needed for this report and store in the class */ private function query_report_data() { global $wpdb; // Convert from Decimal format(eg. 11.5) to a suitable format(eg. +11:30) for CONVERT_TZ() of SQL query. $offset = get_option( 'gmt_offset' ); $site_timezone = sprintf( '%+02d:%02d', (int) $offset, ( $offset - floor( $offset ) ) * 60 ); $retry_date_in_local_time = $wpdb->prepare( "CONVERT_TZ(retries.date_gmt, '+00:00', %s)", $site_timezone ); // We need to compute this on our own since 'group_by_query' from the parent class uses posts table column names. switch ( $this->chart_groupby ) { case 'day': $this->group_by_query = "YEAR({$retry_date_in_local_time}), MONTH({$retry_date_in_local_time}), DAY({$retry_date_in_local_time})"; break; case 'month': $this->group_by_query = "YEAR({$retry_date_in_local_time}), MONTH({$retry_date_in_local_time})"; break; } $this->report_data = new stdClass; $query_start_date = get_gmt_from_date( date( 'Y-m-d H:i:s', $this->start_date ) ); $query_end_date = get_gmt_from_date( date( 'Y-m-d H:i:s', wcs_strtotime_dark_knight( '+1 day', $this->end_date ) ) ); // Get the sum of order totals for completed retries (i.e. retries which eventually succeeded in processing the failed payment) $renewal_query = $wpdb->prepare( " SELECT COUNT(DISTINCT retries.retry_id) as count, MIN(retries.date_gmt) AS retry_date_gmt, MIN({$retry_date_in_local_time}) AS retry_date, SUM(meta_order_total.meta_value) AS renewal_totals FROM {$wpdb->posts} AS orders INNER JOIN {$wpdb->prefix}wcs_payment_retries AS retries ON ( orders.ID = retries.order_id ) LEFT JOIN {$wpdb->postmeta} AS meta_order_total ON ( orders.ID = meta_order_total.post_id AND meta_order_total.meta_key = '_order_total' ) WHERE retries.status = 'complete' AND retries.date_gmt >= %s AND retries.date_gmt < %s GROUP BY {$this->group_by_query} ORDER BY retry_date_gmt ASC ", $query_start_date, $query_end_date ); $this->report_data->renewal_data = $wpdb->get_results( $renewal_query ); // Get the counts for all retries, grouped by day or month and status $retry_query = $wpdb->prepare( " SELECT COUNT(DISTINCT retries.retry_id) AS count, retries.status AS status, MIN(retries.date_gmt) AS retry_date_gmt, MIN({$retry_date_in_local_time}) AS retry_date FROM {$wpdb->prefix}wcs_payment_retries AS retries WHERE retries.status IN ( 'complete', 'failed', 'pending' ) AND retries.date_gmt >= %s AND retries.date_gmt < %s GROUP BY {$this->group_by_query}, status ORDER BY retry_date_gmt ASC ", $query_start_date, $query_end_date ); $this->report_data->retry_data = $wpdb->get_results( $retry_query ); // Total up the query data $this->report_data->retry_failed_count = absint( array_sum( wp_list_pluck( wp_list_filter( $this->report_data->retry_data, array( 'status' => 'failed' ) ), 'count' ) ) ); $this->report_data->retry_success_count = absint( array_sum( wp_list_pluck( wp_list_filter( $this->report_data->retry_data, array( 'status' => 'complete' ) ), 'count' ) ) ); $this->report_data->retry_pending_count = absint( array_sum( wp_list_pluck( wp_list_filter( $this->report_data->retry_data, array( 'status' => 'pending' ) ), 'count' ) ) ); $this->report_data->renewal_total_count = absint( array_sum( wp_list_pluck( $this->report_data->renewal_data, 'count' ) ) ); $this->report_data->renewal_total_amount = array_sum( wp_list_pluck( $this->report_data->renewal_data, 'renewal_totals' ) ); } /** * Get the legend for the main chart sidebar * @return array */ public function get_chart_legend() { $legend = array(); $data = $this->get_report_data(); $legend[] = array( // translators: %s: formatted amount. 'title' => sprintf( __( '%s renewal revenue recovered', 'woocommerce-subscriptions' ), '' . wc_price( $data->renewal_total_amount ) . '' ), 'placeholder' => __( 'The total amount of revenue, including tax and shipping, recovered with the failed payment retry system for renewal orders with a failed payment.', 'woocommerce-subscriptions' ), 'color' => $this->chart_colours['renewal_total'], 'highlight_series' => 3, ); $legend[] = array( // translators: %s: renewal count. 'title' => sprintf( __( '%s renewal orders', 'woocommerce-subscriptions' ), '' . $data->renewal_total_count . '' ), 'placeholder' => __( 'The number of renewal orders which had a failed payment use the retry system.', 'woocommerce-subscriptions' ), 'color' => $this->chart_colours['renewal_count'], ); $legend[] = array( // translators: %s: retry count. 'title' => sprintf( __( '%s retry attempts succeeded', 'woocommerce-subscriptions' ), '' . $data->retry_success_count . '' ), 'placeholder' => __( 'The number of renewal payment retries for this period which were able to process the payment which had previously failed one or more times.', 'woocommerce-subscriptions' ), 'color' => $this->chart_colours['retry_success_count'], 'highlight_series' => 0, ); $legend[] = array( // translators: %s: retry count. 'title' => sprintf( __( '%s retry attempts failed', 'woocommerce-subscriptions' ), '' . $data->retry_failed_count . '' ), 'placeholder' => __( 'The number of renewal payment retries for this period which did not result in a successful payment.', 'woocommerce-subscriptions' ), 'color' => $this->chart_colours['retry_failure_count'], 'highlight_series' => 1, ); $legend[] = array( // translators: %s: retry count. 'title' => sprintf( __( '%s retry attempts pending', 'woocommerce-subscriptions' ), '' . $data->retry_pending_count . '' ), 'placeholder' => __( 'The number of renewal payment retries not yet processed.', 'woocommerce-subscriptions' ), 'color' => $this->chart_colours['retry_pending_count'], 'highlight_series' => 2, ); return $legend; } /** * Output the report */ public function output_report() { $ranges = array( 'year' => __( 'Year', 'woocommerce-subscriptions' ), 'last_month' => __( 'Last Month', 'woocommerce-subscriptions' ), 'month' => __( 'This Month', 'woocommerce-subscriptions' ), '7day' => __( 'Last 7 Days', 'woocommerce-subscriptions' ), ); $this->chart_colours = array( 'retry_success_count' => '#5cc488', 'retry_failure_count' => '#e74c3c', 'retry_pending_count' => '#dbe1e3', 'renewal_count' => '#b1d4ea', 'renewal_total' => '#3498db', ); $current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : '7day'; if ( ! in_array( $current_range, array( 'custom', 'year', 'last_month', 'month', '7day' ) ) ) { $current_range = '7day'; } $this->calculate_current_range( $current_range ); include( WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php' ); } /** * Output an export link */ public function get_export_button() { $current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( $_GET['range'] ) : '7day'; ?> prepare_chart_data( $this->report_data->retry_data, 'retry_date', 'count', $this->chart_interval, $this->start_date, $this->chart_groupby ); $retry_success_count = $this->prepare_chart_data( wp_list_filter( $this->report_data->retry_data, array( 'status' => 'complete' ) ), 'retry_date', 'count', $this->chart_interval, $this->start_date, $this->chart_groupby ); $retry_failure_count = $this->prepare_chart_data( wp_list_filter( $this->report_data->retry_data, array( 'status' => 'failed' ) ), 'retry_date', 'count', $this->chart_interval, $this->start_date, $this->chart_groupby ); $retry_pending_count = $this->prepare_chart_data( wp_list_filter( $this->report_data->retry_data, array( 'status' => 'pending' ) ), 'retry_date', 'count', $this->chart_interval, $this->start_date, $this->chart_groupby ); $renewal_count = $this->prepare_chart_data( $this->report_data->renewal_data, 'retry_date', 'count', $this->chart_interval, $this->start_date, $this->chart_groupby ); $renewal_amount = $this->prepare_chart_data( $this->report_data->renewal_data, 'retry_date', 'renewal_totals', $this->chart_interval, $this->start_date, $this->chart_groupby ); // Encode in json format $chart_data = array( 'retry_count' => array_values( $retry_count ), 'retry_success_count' => array_values( $retry_success_count ), 'retry_failure_count' => array_values( $retry_failure_count ), 'retry_pending_count' => array_values( $retry_pending_count ), 'renewal_count' => array_values( $renewal_count ), 'renewal_amount' => array_map( array( $this, 'round_chart_totals' ), array_values( $renewal_amount ) ), ); $timeformat = ( $this->chart_groupby == 'day' ? '%d %b' : '%b' ); ?>