Schema::date(), 'end_date' => Schema::date(), 'compare' => Schema::compare(), ), array( 'start_date', 'end_date' ) ); } /** * Runs the data function. * * @param array $args Validated arguments. * @return array */ public function run( array $args ): array { $period = Schema::period( $args ); $current = self::fetch( $period, true ); $result = array( 'period' => $period->to_array(), 'totals' => $current['totals'], 'rows_read' => $current['totals']['orders'], 'notes' => array( 'Net sales exclude refunds, coupons, taxes and shipping, as in WooCommerce Analytics.' ), ); $compare = (string) ( $args['compare'] ?? 'none' ); if ( 'none' !== $compare ) { $previous_period = $period->comparison( $compare ); $previous = self::fetch( $previous_period, false ); $result['comparison'] = array( 'period' => $previous_period->to_array(), 'totals' => $previous['totals'], 'change' => self::change( $current['totals'], $previous['totals'] ), ); $result['rows_read'] += $previous['totals']['orders']; } $result['chart'] = array( 'type' => 'line', 'title' => __( 'Net sales', 'askshelf' ), 'format' => 'money', 'points' => $current['series'], ); return $result; } /** * Totals and series for one period. * * @param Period $period Period. * @param bool $with_series Also fetch intervals. * @return array{totals: array, series: list} */ private static function fetch( Period $period, bool $with_series ): array { $response = Analytics::get( '/reports/revenue/stats', array( 'after' => $period->after(), 'before' => $period->before(), 'interval' => $period->chart_interval(), 'per_page' => 100, 'order' => 'asc', ) ); $data = is_array( $response['data'] ) ? $response['data'] : array(); $totals = is_array( $data['totals'] ?? null ) ? $data['totals'] : array(); $orders = (int) ( $totals['orders_count'] ?? 0 ); $net = Analytics::money( $totals['net_revenue'] ?? 0 ); $out = array( 'net_sales' => $net, 'gross_sales' => Analytics::money( $totals['gross_sales'] ?? 0 ), 'total_sales' => Analytics::money( $totals['total_sales'] ?? 0 ), 'orders' => $orders, 'average_order' => $orders > 0 ? Analytics::money( $net / $orders ) : 0.0, 'items_sold' => (int) ( $totals['num_items_sold'] ?? 0 ), 'refunds' => Analytics::money( $totals['refunds'] ?? 0 ), 'coupon_discount' => Analytics::money( $totals['coupons'] ?? 0 ), 'shipping' => Analytics::money( $totals['shipping'] ?? 0 ), 'taxes' => Analytics::money( $totals['taxes'] ?? 0 ), ); $series = array(); if ( $with_series && is_array( $data['intervals'] ?? null ) ) { foreach ( $data['intervals'] as $interval ) { $series[] = array( 'label' => (string) ( $interval['date_start'] ?? $interval['interval'] ?? '' ), 'value' => Analytics::money( $interval['subtotals']['net_revenue'] ?? 0 ), ); } } return array( 'totals' => $out, 'series' => $series, ); } /** * Percentage changes, or null where the previous value is zero. * * @param array $current Current totals. * @param array $previous Previous totals. * @return array */ public static function change( array $current, array $previous ): array { $change = array(); foreach ( $current as $key => $value ) { $before = (float) ( $previous[ $key ] ?? 0 ); $change[ $key ] = 0.0 === $before ? null : round( ( (float) $value - $before ) / abs( $before ) * 100, 1 ) + 0.0; // + 0.0 turns -0.0 into 0.0. } return $change; } }