Passed
Push — master ( 73761a...194fb3 )
by Brian
04:00
created
includes/api/class-getpaid-rest-report-sales-controller.php 1 patch
Indentation   +659 added lines, -659 removed lines patch added patch discarded remove patch
@@ -18,664 +18,664 @@
 block discarded – undo
18 18
  */
19 19
 class GetPaid_REST_Report_Sales_Controller extends GetPaid_REST_Date_Based_Controller {
20 20
 
21
-	/**
22
-	 * Route base.
23
-	 *
24
-	 * @var string
25
-	 */
26
-	protected $rest_base = 'reports/sales';
27
-
28
-	/**
29
-	 * The report data.
30
-	 *
31
-	 * @var stdClass
32
-	 */
33
-	protected $report_data;
34
-
35
-	/**
36
-	 * The report range.
37
-	 *
38
-	 * @var array
39
-	 */
40
-	protected $report_range;
41
-
42
-	/**
43
-	 * Registers the routes for the objects of the controller.
44
-	 *
45
-	 * @since 2.0.0
46
-	 *
47
-	 * @see register_rest_route()
48
-	 */
49
-	public function register_namespace_routes( $namespace ) {
50
-
51
-		// Get sales report.
52
-		register_rest_route(
53
-			$namespace,
54
-			$this->rest_base,
55
-			array(
56
-				array(
57
-					'methods'             => WP_REST_Server::READABLE,
58
-					'callback'            => array( $this, 'get_items' ),
59
-					'permission_callback' => array( $this, 'get_items_permissions_check' ),
60
-					'args'                => $this->get_collection_params(),
61
-				),
62
-				'schema' => array( $this, 'get_public_item_schema' ),
63
-			)
64
-		);
65
-
66
-	}
67
-
68
-	/**
69
-	 * Makes sure the current user has access to READ the report APIs.
70
-	 *
71
-	 * @since  2.0.0
72
-	 * @param WP_REST_Request $request Full data about the request.
73
-	 * @return WP_Error|boolean
74
-	 */
75
-	public function get_items_permissions_check( $request ) {
76
-
77
-		if ( ! wpinv_current_user_can_manage_invoicing() ) {
78
-			return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot list resources.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) );
79
-		}
80
-
81
-		return true;
82
-	}
83
-
84
-	/**
85
-	 * Get sales reports.
86
-	 *
87
-	 * @param WP_REST_Request $request
88
-	 * @return array|WP_Error
89
-	 */
90
-	public function get_items( $request ) {
91
-		$data   = array();
92
-		$item   = $this->prepare_item_for_response( null, $request );
93
-		$data[] = $this->prepare_response_for_collection( $item );
94
-
95
-		return rest_ensure_response( $data );
96
-	}
97
-
98
-	/**
99
-	 * Prepare a report sales object for serialization.
100
-	 *
101
-	 * @param null $_
102
-	 * @param WP_REST_Request $request Request object.
103
-	 * @return WP_REST_Response $response Response data.
104
-	 */
105
-	public function prepare_item_for_response( $_, $request ) {
106
-
107
-		// Set report range.
108
-		$this->report_range = $this->get_date_range( $request );
109
-
110
-		$report_data     = $this->get_report_data();
111
-		$period_totals   = array();
112
-
113
-		// Setup period totals by ensuring each period in the interval has data.
114
-		$start_date      = strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS;
115
-
116
-		if ( 'month' === $this->groupby ) {
117
-			$start_date      = strtotime( date( 'Y-m-01', $start_date ) );
118
-		}
119
-
120
-		for ( $i = 0; $i < $this->interval; $i++ ) {
121
-
122
-			switch ( $this->groupby ) {
123
-				case 'day' :
124
-					$time = date( 'Y-m-d', strtotime( "+{$i} DAY", $start_date ) );
125
-					break;
126
-				default :
127
-					$time = date( 'Y-m', strtotime( "+{$i} MONTH", $start_date ) );
128
-					break;
129
-			}
130
-
131
-			// Set the defaults for each period.
132
-			$period_totals[ $time ] = array(
133
-				'sales'             => wpinv_round_amount( 0.00 ),
134
-				'invoices'          => 0,
135
-				'refunds'           => wpinv_round_amount( 0.00 ),
136
-				'items'             => 0,
137
-				'refunded_items'    => 0,
138
-				'tax'               => wpinv_round_amount( 0.00 ),
139
-				'refunded_tax'      => wpinv_round_amount( 0.00 ),
140
-				'subtotal'          => wpinv_round_amount( 0.00 ),
141
-				'refunded_subtotal' => wpinv_round_amount( 0.00 ),
142
-				'fees'              => wpinv_round_amount( 0.00 ),
143
-				'refunded_fees'     => wpinv_round_amount( 0.00 ),
144
-				'discount'          => wpinv_round_amount( 0.00 ),
145
-			);
146
-
147
-		}
148
-
149
-		// add total sales, total invoice count, total tax for each period
150
-		$date_format = ( 'day' === $this->groupby ) ? 'Y-m-d' : 'Y-m';
151
-		foreach ( $report_data->invoices as $invoice ) {
152
-			$time = date( $date_format, strtotime( $invoice->post_date ) );
153
-
154
-			if ( ! isset( $period_totals[ $time ] ) ) {
155
-				continue;
156
-			}
157
-
158
-			$period_totals[ $time ]['sales']    = wpinv_round_amount( $invoice->total_sales );
159
-			$period_totals[ $time ]['tax']      = wpinv_round_amount( $invoice->total_tax );
160
-			$period_totals[ $time ]['subtotal'] = wpinv_round_amount( $invoice->subtotal );
161
-			$period_totals[ $time ]['fees']     = wpinv_round_amount( $invoice->total_fees );
162
-
163
-		}
164
-
165
-		foreach ( $report_data->refunds as $invoice ) {
166
-			$time = date( $date_format, strtotime( $invoice->post_date ) );
167
-
168
-			if ( ! isset( $period_totals[ $time ] ) ) {
169
-				continue;
170
-			}
171
-
172
-			$period_totals[ $time ]['refunds']           = wpinv_round_amount( $invoice->total_sales );
173
-			$period_totals[ $time ]['refunded_tax']      = wpinv_round_amount( $invoice->total_tax );
174
-			$period_totals[ $time ]['refunded_subtotal'] = wpinv_round_amount( $invoice->subtotal );
175
-			$period_totals[ $time ]['refunded_fees']     = wpinv_round_amount( $invoice->total_fees );
176
-
177
-		}
178
-
179
-		foreach ( $report_data->invoice_counts as $invoice ) {
180
-			$time = date( $date_format, strtotime( $invoice->post_date ) );
181
-
182
-			if ( isset( $period_totals[ $time ] ) ) {
183
-				$period_totals[ $time ]['invoices']   = (int) $invoice->count;
184
-			}
185
-
186
-		}
187
-
188
-		// Add total invoice items for each period.
189
-		foreach ( $report_data->invoice_items as $invoice_item ) {
190
-			$time = ( 'day' === $this->groupby ) ? date( 'Y-m-d', strtotime( $invoice_item->post_date ) ) : date( 'Y-m', strtotime( $invoice_item->post_date ) );
191
-
192
-			if ( isset( $period_totals[ $time ] ) ) {
193
-				$period_totals[ $time ]['items'] = (int) $invoice_item->invoice_item_count;
194
-			}
195
-
196
-		}
197
-
198
-		// Add total discount for each period.
199
-		foreach ( $report_data->coupons as $discount ) {
200
-			$time = ( 'day' === $this->groupby ) ? date( 'Y-m-d', strtotime( $discount->post_date ) ) : date( 'Y-m', strtotime( $discount->post_date ) );
201
-
202
-			if ( isset( $period_totals[ $time ] ) ) {
203
-				$period_totals[ $time ]['discount'] = wpinv_round_amount( $discount->discount_amount );
204
-			}
205
-
206
-		}
207
-
208
-		$report_data->totals            = $period_totals;
209
-		$report_data->grouped_by        = $this->groupby;
210
-		$report_data->interval          = max( $this->interval, 1 );
211
-		$report_data->currency          = wpinv_get_currency();
212
-		$report_data->currency_symbol   = wpinv_currency_symbol();
213
-		$report_data->currency_position = wpinv_currency_position();
214
-		$report_data->decimal_places    = wpinv_decimals();
215
-		$report_data->thousands_sep     = wpinv_thousands_separator();
216
-		$report_data->decimals_sep      = wpinv_decimal_separator();
217
-		$report_data->start_date        = date( 'Y-m-d', strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS );
218
-		$report_data->end_date          = date( 'Y-m-d', strtotime( $this->report_range['before'] ) - DAY_IN_SECONDS );
219
-		$report_data->start_date_locale = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS ) );
220
-		$report_data->end_date_locale   = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['before'] ) - DAY_IN_SECONDS ) );
221
-		$report_data->decimals_sep      = wpinv_decimal_separator();
222
-
223
-		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
224
-		$data    = $report_data;
225
-		unset( $data->invoice_counts, $data->invoices, $data->coupons, $data->refunds, $data->invoice_items );
226
-		$data    = $this->add_additional_fields_to_object( (array) $data, $request );
227
-		$data    = $this->filter_response_by_context( $data, $context );
228
-
229
-		// Wrap the data in a response object.
230
-		$response = rest_ensure_response( $data );
231
-		$response->add_links( array(
232
-			'about' => array(
233
-				'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
234
-			),
235
-		) );
236
-
237
-		return apply_filters( 'getpaid_rest_prepare_report_sales', $response, $report_data, $request );
238
-	}
239
-
240
-	/**
241
-	 * Get report data.
242
-	 *
243
-	 * @return stdClass
244
-	 */
245
-	public function get_report_data() {
246
-		if ( empty( $this->report_data ) ) {
247
-			$this->query_report_data();
248
-		}
249
-		return $this->report_data;
250
-	}
251
-
252
-	/**
253
-	 * Get all data needed for this report and store in the class.
254
-	 */
255
-	protected function query_report_data() {
256
-
257
-		// Prepare reports.
258
-		$this->report_data = (object) array(
259
-			'invoice_counts' => $this->query_invoice_counts(),//count, post_date
260
-			'coupons'        => $this->query_coupon_counts(), // discount_amount, post_date
261
-			'invoice_items'  => $this->query_item_counts(), // invoice_item_count, post_date
262
-			'refunded_items' => $this->count_refunded_items(), // invoice_item_count, post_date
263
-			'invoices'       => $this->query_invoice_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
264
-			'refunds'        => $this->query_refunded_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
265
-			'previous_range' => $this->previous_range,
266
-		);
267
-
268
-		// Calculated totals.
269
-		$this->report_data->total_tax          = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_tax' ) ) );
270
-		$this->report_data->total_sales        = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_sales' ) ) );
271
-		$this->report_data->total_discount     = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_discount' ) ) );
272
-		$this->report_data->total_fees         = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_fees' ) ) );
273
-		$this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'subtotal' ) ) );
274
-		$this->report_data->net_sales          = wpinv_round_amount( $this->report_data->total_sales - max( 0, $this->report_data->total_tax ) );
275
-		$this->report_data->total_refunded_tax = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_tax' ) ) );
276
-		$this->report_data->total_refunds      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_sales' ) ) );
277
-		$this->report_data->refunded_discount  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_discount' ) ) );
278
-		$this->report_data->refunded_fees      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_fees' ) ) );
279
-		$this->report_data->refunded_subtotal  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'subtotal' ) ) );
280
-		$this->report_data->net_refunds        = wpinv_round_amount( $this->report_data->total_refunds + max( 0, $this->report_data->total_refunded_tax ) );
281
-
282
-
283
-		// Calculate average based on net.
284
-		$this->report_data->average_sales       = wpinv_round_amount( $this->report_data->net_sales / max( $this->interval, 1 ), 2 );
285
-		$this->report_data->average_total_sales = wpinv_round_amount( $this->report_data->total_sales / max( $this->interval, 1 ), 2 );
286
-
287
-		// Total invoices in this period, even if refunded.
288
-		$this->report_data->total_invoices = absint( array_sum( wp_list_pluck( $this->report_data->invoice_counts, 'count' ) ) );
289
-
290
-		// Items invoiced in this period, even if refunded.
291
-		$this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->invoice_items, 'invoice_item_count' ) ) );
292
-
293
-		// 3rd party filtering of report data
294
-		$this->report_data = apply_filters( 'getpaid_rest_api_filter_report_data', $this->report_data );
295
-	}
296
-
297
-	/**
298
-	 * Prepares invoice counts.
299
-	 *
300
-	 * @return array.
301
-	 */
302
-	protected function query_invoice_counts() {
303
-
304
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
305
-			array(
306
-				'data'         => array(
307
-					'ID'        => array(
308
-						'type'     => 'post_data',
309
-						'function' => 'COUNT',
310
-						'name'     => 'count',
311
-						'distinct' => true,
312
-					),
313
-					'post_date' => array(
314
-						'type'     => 'post_data',
315
-						'function' => '',
316
-						'name'     => 'post_date',
317
-					),
318
-				),
319
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
320
-				'order_by'       => 'post_date ASC',
321
-				'query_type'     => 'get_results',
322
-				'filter_range'   => $this->report_range,
323
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
324
-			)
325
-		);
326
-
327
-	}
328
-
329
-	/**
330
-	 * Prepares coupon counts.
331
-	 *
332
-	 * @return array.
333
-	 */
334
-	protected function query_coupon_counts() {
335
-
336
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
337
-			array(
338
-				'data'         => array(
339
-					'discount' => array(
340
-						'type'     => 'invoice_data',
341
-						'function' => 'SUM',
342
-						'name'     => 'discount_amount',
343
-					),
344
-					'post_date'       => array(
345
-						'type'     => 'post_data',
346
-						'function' => '',
347
-						'name'     => 'post_date',
348
-					),
349
-				),
350
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
351
-				'order_by'       => 'post_date ASC',
352
-				'query_type'     => 'get_results',
353
-				'filter_range'   => $this->report_range,
354
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
355
-			)
356
-		);
357
-
358
-	}
359
-
360
-	/**
361
-	 * Prepares item counts.
362
-	 *
363
-	 * @return array.
364
-	 */
365
-	protected function query_item_counts() {
366
-
367
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
368
-			array(
369
-				'data'         => array(
370
-					'quantity'      => array(
371
-						'type'            => 'invoice_item',
372
-						'function'        => 'SUM',
373
-						'name'            => 'invoice_item_count',
374
-					),
375
-					'post_date' => array(
376
-						'type'     => 'post_data',
377
-						'function' => '',
378
-						'name'     => 'post_date',
379
-					),
380
-				),
381
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
382
-				'order_by'       => 'post_date ASC',
383
-				'query_type'     => 'get_results',
384
-				'filter_range'   => $this->report_range,
385
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
386
-			)
387
-		);
388
-
389
-	}
390
-
391
-	/**
392
-	 * Prepares refunded item counts.
393
-	 *
394
-	 * @return array.
395
-	 */
396
-	protected function count_refunded_items() {
397
-
398
-		return (int) GetPaid_Reports_Helper::get_invoice_report_data(
399
-			array(
400
-				'data'         => array(
401
-					'quantity'      => array(
402
-						'type'            => 'invoice_item',
403
-						'function'        => 'SUM',
404
-						'name'            => 'invoice_item_count',
405
-					),
406
-				),
407
-				'query_type'     => 'get_var',
408
-				'filter_range'   => $this->report_range,
409
-				'invoice_status' => array( 'wpi-refunded' ),
410
-			)
411
-		);
412
-
413
-	}
414
-
415
-	/**
416
-	 * Prepares daily invoice totals.
417
-	 *
418
-	 * @return array.
419
-	 */
420
-	protected function query_invoice_totals() {
421
-
422
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
423
-			array(
424
-				'data'         => array(
425
-					'total'      => array(
426
-						'type'            => 'invoice_data',
427
-						'function'        => 'SUM',
428
-						'name'            => 'total_sales',
429
-					),
430
-					'tax'      => array(
431
-						'type'            => 'invoice_data',
432
-						'function'        => 'SUM',
433
-						'name'            => 'total_tax',
434
-					),
435
-					'discount'      => array(
436
-						'type'            => 'invoice_data',
437
-						'function'        => 'SUM',
438
-						'name'            => 'total_discount',
439
-					),
440
-					'fees_total'      => array(
441
-						'type'            => 'invoice_data',
442
-						'function'        => 'SUM',
443
-						'name'            => 'total_fees',
444
-					),
445
-					'subtotal'      => array(
446
-						'type'            => 'invoice_data',
447
-						'function'        => 'SUM',
448
-						'name'            => 'subtotal',
449
-					),
450
-					'post_date' => array(
451
-						'type'     => 'post_data',
452
-						'function' => '',
453
-						'name'     => 'post_date',
454
-					),
455
-				),
456
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
457
-				'order_by'       => 'post_date ASC',
458
-				'query_type'     => 'get_results',
459
-				'filter_range'   => $this->report_range,
460
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-renewal' ),
461
-			)
462
-		);
463
-
464
-	}
465
-
466
-	/**
467
-	 * Prepares daily invoice totals.
468
-	 *
469
-	 * @return array.
470
-	 */
471
-	protected function query_refunded_totals() {
472
-
473
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
474
-			array(
475
-				'data'         => array(
476
-					'total'      => array(
477
-						'type'            => 'invoice_data',
478
-						'function'        => 'SUM',
479
-						'name'            => 'total_sales',
480
-					),
481
-					'tax'      => array(
482
-						'type'            => 'invoice_data',
483
-						'function'        => 'SUM',
484
-						'name'            => 'total_tax',
485
-					),
486
-					'discount'      => array(
487
-						'type'            => 'invoice_data',
488
-						'function'        => 'SUM',
489
-						'name'            => 'total_discount',
490
-					),
491
-					'fees_total'      => array(
492
-						'type'            => 'invoice_data',
493
-						'function'        => 'SUM',
494
-						'name'            => 'total_fees',
495
-					),
496
-					'subtotal'      => array(
497
-						'type'            => 'invoice_data',
498
-						'function'        => 'SUM',
499
-						'name'            => 'subtotal',
500
-					),
501
-					'post_date' => array(
502
-						'type'     => 'post_data',
503
-						'function' => '',
504
-						'name'     => 'post_date',
505
-					),
506
-				),
507
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
508
-				'order_by'       => 'post_date ASC',
509
-				'query_type'     => 'get_results',
510
-				'filter_range'   => $this->report_range,
511
-				'invoice_status' => array( 'wpi-refunded' ),
512
-			)
513
-		);
514
-
515
-	}
516
-
517
-	/**
518
-	 * Get the Report's schema, conforming to JSON Schema.
519
-	 *
520
-	 * @return array
521
-	 */
522
-	public function get_item_schema() {
523
-
524
-		$schema = array(
525
-			'$schema'    => 'http://json-schema.org/draft-04/schema#',
526
-			'title'      => 'sales_report',
527
-			'type'       => 'object',
528
-			'properties' => array(
529
-				'total_sales' => array(
530
-					'description' => __( 'Gross sales in the period.', 'invoicing' ),
531
-					'type'        => 'string',
532
-					'context'     => array( 'view' ),
533
-					'readonly'    => true,
534
-				),
535
-				'net_sales' => array(
536
-					'description' => __( 'Net sales in the period.', 'invoicing' ),
537
-					'type'        => 'string',
538
-					'context'     => array( 'view' ),
539
-					'readonly'    => true,
540
-				),
541
-				'average_sales' => array(
542
-					'description' => __( 'Average net daily sales.', 'invoicing' ),
543
-					'type'        => 'string',
544
-					'context'     => array( 'view' ),
545
-					'readonly'    => true,
546
-				),
547
-				'average_total_sales' => array(
548
-					'description' => __( 'Average gross daily sales.', 'invoicing' ),
549
-					'type'        => 'string',
550
-					'context'     => array( 'view' ),
551
-					'readonly'    => true,
552
-				),
553
-				'total_invoices'  => array(
554
-					'description' => __( 'Number of paid invoices.', 'invoicing' ),
555
-					'type'        => 'integer',
556
-					'context'     => array( 'view' ),
557
-					'readonly'    => true,
558
-				),
559
-				'total_items' => array(
560
-					'description' => __( 'Number of items purchased.', 'invoicing' ),
561
-					'type'        => 'integer',
562
-					'context'     => array( 'view' ),
563
-					'readonly'    => true,
564
-				),
565
-				'refunded_items' => array(
566
-					'description' => __( 'Number of items refunded.', 'invoicing' ),
567
-					'type'        => 'integer',
568
-					'context'     => array( 'view' ),
569
-					'readonly'    => true,
570
-				),
571
-				'total_tax' => array(
572
-					'description' => __( 'Total charged for taxes.', 'invoicing' ),
573
-					'type'        => 'string',
574
-					'context'     => array( 'view' ),
575
-					'readonly'    => true,
576
-				),
577
-				'total_refunded_tax' => array(
578
-					'description' => __( 'Total refunded for taxes.', 'invoicing' ),
579
-					'type'        => 'string',
580
-					'context'     => array( 'view' ),
581
-					'readonly'    => true,
582
-				),
583
-				'total_fees' => array(
584
-					'description' => __( 'Total fees charged.', 'invoicing' ),
585
-					'type'        => 'string',
586
-					'context'     => array( 'view' ),
587
-					'readonly'    => true,
588
-				),
589
-				'total_refunds' => array(
590
-					'description' => __( 'Total of refunded invoices.', 'invoicing' ),
591
-					'type'        => 'integer',
592
-					'context'     => array( 'view' ),
593
-					'readonly'    => true,
594
-				),
595
-				'net_refunds' => array(
596
-					'description' => __( 'Net of refunded invoices.', 'invoicing' ),
597
-					'type'        => 'integer',
598
-					'context'     => array( 'view' ),
599
-					'readonly'    => true,
600
-				),
601
-				'total_discount' => array(
602
-					'description' => __( 'Total of discounts used.', 'invoicing' ),
603
-					'type'        => 'integer',
604
-					'context'     => array( 'view' ),
605
-					'readonly'    => true,
606
-				),
607
-				'totals' => array(
608
-					'description' => __( 'Totals.', 'invoicing' ),
609
-					'type'        => 'array',
610
-					'items'       => array(
611
-						'type'    => 'array',
612
-					),
613
-					'context'     => array( 'view' ),
614
-					'readonly'    => true,
615
-				),
616
-				'interval' => array(
617
-					'description' => __( 'Number of months/days in the report period.', 'invoicing' ),
618
-					'type'        => 'integer',
619
-					'context'     => array( 'view' ),
620
-					'readonly'    => true,
621
-				),
622
-				'previous_range'  => array(
623
-					'description' => __( 'The previous report period.', 'invoicing' ),
624
-					'type'        => 'array',
625
-					'items'       => array(
626
-						'type'    => 'string',
627
-					),
628
-					'context'     => array( 'view' ),
629
-					'readonly'    => true,
630
-				),
631
-				'grouped_by' => array(
632
-					'description' => __( 'The period used to group the totals.', 'invoicing' ),
633
-					'type'        => 'string',
634
-					'context'     => array( 'view' ),
635
-					'enum'        => array( 'day', 'month' ),
636
-					'readonly'    => true,
637
-				),
638
-				'currency' => array(
639
-					'description' => __( 'The default store currency.', 'invoicing' ),
640
-					'type'        => 'string',
641
-					'context'     => array( 'view' ),
642
-					'readonly'    => true,
643
-				),
644
-				'currency_symbol' => array(
645
-					'description' => __( 'The default store currency symbol.', 'invoicing' ),
646
-					'type'        => 'string',
647
-					'context'     => array( 'view' ),
648
-					'readonly'    => true,
649
-				),
650
-				'currency_position' => array(
651
-					'description' => __( 'The default store currency position.', 'invoicing' ),
652
-					'type'        => 'string',
653
-					'context'     => array( 'view' ),
654
-					'readonly'    => true,
655
-				),
656
-				'decimal_places' => array(
657
-					'description' => __( 'The default store decimal places.', 'invoicing' ),
658
-					'type'        => 'string',
659
-					'context'     => array( 'view' ),
660
-					'readonly'    => true,
661
-				),
662
-				'thousands_sep' => array(
663
-					'description' => __( 'The default store thousands separator.', 'invoicing' ),
664
-					'type'        => 'string',
665
-					'context'     => array( 'view' ),
666
-					'readonly'    => true,
667
-				),
668
-				'decimals_sep' => array(
669
-					'description' => __( 'The default store decimals separator.', 'invoicing' ),
670
-					'type'        => 'string',
671
-					'context'     => array( 'view' ),
672
-					'readonly'    => true,
673
-				),
674
-			),
675
-		);
676
-
677
-		return $this->add_additional_fields_schema( $schema );
678
-
679
-	}
21
+    /**
22
+     * Route base.
23
+     *
24
+     * @var string
25
+     */
26
+    protected $rest_base = 'reports/sales';
27
+
28
+    /**
29
+     * The report data.
30
+     *
31
+     * @var stdClass
32
+     */
33
+    protected $report_data;
34
+
35
+    /**
36
+     * The report range.
37
+     *
38
+     * @var array
39
+     */
40
+    protected $report_range;
41
+
42
+    /**
43
+     * Registers the routes for the objects of the controller.
44
+     *
45
+     * @since 2.0.0
46
+     *
47
+     * @see register_rest_route()
48
+     */
49
+    public function register_namespace_routes( $namespace ) {
50
+
51
+        // Get sales report.
52
+        register_rest_route(
53
+            $namespace,
54
+            $this->rest_base,
55
+            array(
56
+                array(
57
+                    'methods'             => WP_REST_Server::READABLE,
58
+                    'callback'            => array( $this, 'get_items' ),
59
+                    'permission_callback' => array( $this, 'get_items_permissions_check' ),
60
+                    'args'                => $this->get_collection_params(),
61
+                ),
62
+                'schema' => array( $this, 'get_public_item_schema' ),
63
+            )
64
+        );
65
+
66
+    }
67
+
68
+    /**
69
+     * Makes sure the current user has access to READ the report APIs.
70
+     *
71
+     * @since  2.0.0
72
+     * @param WP_REST_Request $request Full data about the request.
73
+     * @return WP_Error|boolean
74
+     */
75
+    public function get_items_permissions_check( $request ) {
76
+
77
+        if ( ! wpinv_current_user_can_manage_invoicing() ) {
78
+            return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot list resources.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) );
79
+        }
80
+
81
+        return true;
82
+    }
83
+
84
+    /**
85
+     * Get sales reports.
86
+     *
87
+     * @param WP_REST_Request $request
88
+     * @return array|WP_Error
89
+     */
90
+    public function get_items( $request ) {
91
+        $data   = array();
92
+        $item   = $this->prepare_item_for_response( null, $request );
93
+        $data[] = $this->prepare_response_for_collection( $item );
94
+
95
+        return rest_ensure_response( $data );
96
+    }
97
+
98
+    /**
99
+     * Prepare a report sales object for serialization.
100
+     *
101
+     * @param null $_
102
+     * @param WP_REST_Request $request Request object.
103
+     * @return WP_REST_Response $response Response data.
104
+     */
105
+    public function prepare_item_for_response( $_, $request ) {
106
+
107
+        // Set report range.
108
+        $this->report_range = $this->get_date_range( $request );
109
+
110
+        $report_data     = $this->get_report_data();
111
+        $period_totals   = array();
112
+
113
+        // Setup period totals by ensuring each period in the interval has data.
114
+        $start_date      = strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS;
115
+
116
+        if ( 'month' === $this->groupby ) {
117
+            $start_date      = strtotime( date( 'Y-m-01', $start_date ) );
118
+        }
119
+
120
+        for ( $i = 0; $i < $this->interval; $i++ ) {
121
+
122
+            switch ( $this->groupby ) {
123
+                case 'day' :
124
+                    $time = date( 'Y-m-d', strtotime( "+{$i} DAY", $start_date ) );
125
+                    break;
126
+                default :
127
+                    $time = date( 'Y-m', strtotime( "+{$i} MONTH", $start_date ) );
128
+                    break;
129
+            }
130
+
131
+            // Set the defaults for each period.
132
+            $period_totals[ $time ] = array(
133
+                'sales'             => wpinv_round_amount( 0.00 ),
134
+                'invoices'          => 0,
135
+                'refunds'           => wpinv_round_amount( 0.00 ),
136
+                'items'             => 0,
137
+                'refunded_items'    => 0,
138
+                'tax'               => wpinv_round_amount( 0.00 ),
139
+                'refunded_tax'      => wpinv_round_amount( 0.00 ),
140
+                'subtotal'          => wpinv_round_amount( 0.00 ),
141
+                'refunded_subtotal' => wpinv_round_amount( 0.00 ),
142
+                'fees'              => wpinv_round_amount( 0.00 ),
143
+                'refunded_fees'     => wpinv_round_amount( 0.00 ),
144
+                'discount'          => wpinv_round_amount( 0.00 ),
145
+            );
146
+
147
+        }
148
+
149
+        // add total sales, total invoice count, total tax for each period
150
+        $date_format = ( 'day' === $this->groupby ) ? 'Y-m-d' : 'Y-m';
151
+        foreach ( $report_data->invoices as $invoice ) {
152
+            $time = date( $date_format, strtotime( $invoice->post_date ) );
153
+
154
+            if ( ! isset( $period_totals[ $time ] ) ) {
155
+                continue;
156
+            }
157
+
158
+            $period_totals[ $time ]['sales']    = wpinv_round_amount( $invoice->total_sales );
159
+            $period_totals[ $time ]['tax']      = wpinv_round_amount( $invoice->total_tax );
160
+            $period_totals[ $time ]['subtotal'] = wpinv_round_amount( $invoice->subtotal );
161
+            $period_totals[ $time ]['fees']     = wpinv_round_amount( $invoice->total_fees );
162
+
163
+        }
164
+
165
+        foreach ( $report_data->refunds as $invoice ) {
166
+            $time = date( $date_format, strtotime( $invoice->post_date ) );
167
+
168
+            if ( ! isset( $period_totals[ $time ] ) ) {
169
+                continue;
170
+            }
171
+
172
+            $period_totals[ $time ]['refunds']           = wpinv_round_amount( $invoice->total_sales );
173
+            $period_totals[ $time ]['refunded_tax']      = wpinv_round_amount( $invoice->total_tax );
174
+            $period_totals[ $time ]['refunded_subtotal'] = wpinv_round_amount( $invoice->subtotal );
175
+            $period_totals[ $time ]['refunded_fees']     = wpinv_round_amount( $invoice->total_fees );
176
+
177
+        }
178
+
179
+        foreach ( $report_data->invoice_counts as $invoice ) {
180
+            $time = date( $date_format, strtotime( $invoice->post_date ) );
181
+
182
+            if ( isset( $period_totals[ $time ] ) ) {
183
+                $period_totals[ $time ]['invoices']   = (int) $invoice->count;
184
+            }
185
+
186
+        }
187
+
188
+        // Add total invoice items for each period.
189
+        foreach ( $report_data->invoice_items as $invoice_item ) {
190
+            $time = ( 'day' === $this->groupby ) ? date( 'Y-m-d', strtotime( $invoice_item->post_date ) ) : date( 'Y-m', strtotime( $invoice_item->post_date ) );
191
+
192
+            if ( isset( $period_totals[ $time ] ) ) {
193
+                $period_totals[ $time ]['items'] = (int) $invoice_item->invoice_item_count;
194
+            }
195
+
196
+        }
197
+
198
+        // Add total discount for each period.
199
+        foreach ( $report_data->coupons as $discount ) {
200
+            $time = ( 'day' === $this->groupby ) ? date( 'Y-m-d', strtotime( $discount->post_date ) ) : date( 'Y-m', strtotime( $discount->post_date ) );
201
+
202
+            if ( isset( $period_totals[ $time ] ) ) {
203
+                $period_totals[ $time ]['discount'] = wpinv_round_amount( $discount->discount_amount );
204
+            }
205
+
206
+        }
207
+
208
+        $report_data->totals            = $period_totals;
209
+        $report_data->grouped_by        = $this->groupby;
210
+        $report_data->interval          = max( $this->interval, 1 );
211
+        $report_data->currency          = wpinv_get_currency();
212
+        $report_data->currency_symbol   = wpinv_currency_symbol();
213
+        $report_data->currency_position = wpinv_currency_position();
214
+        $report_data->decimal_places    = wpinv_decimals();
215
+        $report_data->thousands_sep     = wpinv_thousands_separator();
216
+        $report_data->decimals_sep      = wpinv_decimal_separator();
217
+        $report_data->start_date        = date( 'Y-m-d', strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS );
218
+        $report_data->end_date          = date( 'Y-m-d', strtotime( $this->report_range['before'] ) - DAY_IN_SECONDS );
219
+        $report_data->start_date_locale = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS ) );
220
+        $report_data->end_date_locale   = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['before'] ) - DAY_IN_SECONDS ) );
221
+        $report_data->decimals_sep      = wpinv_decimal_separator();
222
+
223
+        $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
224
+        $data    = $report_data;
225
+        unset( $data->invoice_counts, $data->invoices, $data->coupons, $data->refunds, $data->invoice_items );
226
+        $data    = $this->add_additional_fields_to_object( (array) $data, $request );
227
+        $data    = $this->filter_response_by_context( $data, $context );
228
+
229
+        // Wrap the data in a response object.
230
+        $response = rest_ensure_response( $data );
231
+        $response->add_links( array(
232
+            'about' => array(
233
+                'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
234
+            ),
235
+        ) );
236
+
237
+        return apply_filters( 'getpaid_rest_prepare_report_sales', $response, $report_data, $request );
238
+    }
239
+
240
+    /**
241
+     * Get report data.
242
+     *
243
+     * @return stdClass
244
+     */
245
+    public function get_report_data() {
246
+        if ( empty( $this->report_data ) ) {
247
+            $this->query_report_data();
248
+        }
249
+        return $this->report_data;
250
+    }
251
+
252
+    /**
253
+     * Get all data needed for this report and store in the class.
254
+     */
255
+    protected function query_report_data() {
256
+
257
+        // Prepare reports.
258
+        $this->report_data = (object) array(
259
+            'invoice_counts' => $this->query_invoice_counts(),//count, post_date
260
+            'coupons'        => $this->query_coupon_counts(), // discount_amount, post_date
261
+            'invoice_items'  => $this->query_item_counts(), // invoice_item_count, post_date
262
+            'refunded_items' => $this->count_refunded_items(), // invoice_item_count, post_date
263
+            'invoices'       => $this->query_invoice_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
264
+            'refunds'        => $this->query_refunded_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
265
+            'previous_range' => $this->previous_range,
266
+        );
267
+
268
+        // Calculated totals.
269
+        $this->report_data->total_tax          = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_tax' ) ) );
270
+        $this->report_data->total_sales        = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_sales' ) ) );
271
+        $this->report_data->total_discount     = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_discount' ) ) );
272
+        $this->report_data->total_fees         = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_fees' ) ) );
273
+        $this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'subtotal' ) ) );
274
+        $this->report_data->net_sales          = wpinv_round_amount( $this->report_data->total_sales - max( 0, $this->report_data->total_tax ) );
275
+        $this->report_data->total_refunded_tax = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_tax' ) ) );
276
+        $this->report_data->total_refunds      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_sales' ) ) );
277
+        $this->report_data->refunded_discount  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_discount' ) ) );
278
+        $this->report_data->refunded_fees      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_fees' ) ) );
279
+        $this->report_data->refunded_subtotal  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'subtotal' ) ) );
280
+        $this->report_data->net_refunds        = wpinv_round_amount( $this->report_data->total_refunds + max( 0, $this->report_data->total_refunded_tax ) );
281
+
282
+
283
+        // Calculate average based on net.
284
+        $this->report_data->average_sales       = wpinv_round_amount( $this->report_data->net_sales / max( $this->interval, 1 ), 2 );
285
+        $this->report_data->average_total_sales = wpinv_round_amount( $this->report_data->total_sales / max( $this->interval, 1 ), 2 );
286
+
287
+        // Total invoices in this period, even if refunded.
288
+        $this->report_data->total_invoices = absint( array_sum( wp_list_pluck( $this->report_data->invoice_counts, 'count' ) ) );
289
+
290
+        // Items invoiced in this period, even if refunded.
291
+        $this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->invoice_items, 'invoice_item_count' ) ) );
292
+
293
+        // 3rd party filtering of report data
294
+        $this->report_data = apply_filters( 'getpaid_rest_api_filter_report_data', $this->report_data );
295
+    }
296
+
297
+    /**
298
+     * Prepares invoice counts.
299
+     *
300
+     * @return array.
301
+     */
302
+    protected function query_invoice_counts() {
303
+
304
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
305
+            array(
306
+                'data'         => array(
307
+                    'ID'        => array(
308
+                        'type'     => 'post_data',
309
+                        'function' => 'COUNT',
310
+                        'name'     => 'count',
311
+                        'distinct' => true,
312
+                    ),
313
+                    'post_date' => array(
314
+                        'type'     => 'post_data',
315
+                        'function' => '',
316
+                        'name'     => 'post_date',
317
+                    ),
318
+                ),
319
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
320
+                'order_by'       => 'post_date ASC',
321
+                'query_type'     => 'get_results',
322
+                'filter_range'   => $this->report_range,
323
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
324
+            )
325
+        );
326
+
327
+    }
328
+
329
+    /**
330
+     * Prepares coupon counts.
331
+     *
332
+     * @return array.
333
+     */
334
+    protected function query_coupon_counts() {
335
+
336
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
337
+            array(
338
+                'data'         => array(
339
+                    'discount' => array(
340
+                        'type'     => 'invoice_data',
341
+                        'function' => 'SUM',
342
+                        'name'     => 'discount_amount',
343
+                    ),
344
+                    'post_date'       => array(
345
+                        'type'     => 'post_data',
346
+                        'function' => '',
347
+                        'name'     => 'post_date',
348
+                    ),
349
+                ),
350
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
351
+                'order_by'       => 'post_date ASC',
352
+                'query_type'     => 'get_results',
353
+                'filter_range'   => $this->report_range,
354
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
355
+            )
356
+        );
357
+
358
+    }
359
+
360
+    /**
361
+     * Prepares item counts.
362
+     *
363
+     * @return array.
364
+     */
365
+    protected function query_item_counts() {
366
+
367
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
368
+            array(
369
+                'data'         => array(
370
+                    'quantity'      => array(
371
+                        'type'            => 'invoice_item',
372
+                        'function'        => 'SUM',
373
+                        'name'            => 'invoice_item_count',
374
+                    ),
375
+                    'post_date' => array(
376
+                        'type'     => 'post_data',
377
+                        'function' => '',
378
+                        'name'     => 'post_date',
379
+                    ),
380
+                ),
381
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
382
+                'order_by'       => 'post_date ASC',
383
+                'query_type'     => 'get_results',
384
+                'filter_range'   => $this->report_range,
385
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded', 'wpi-renewal' ),
386
+            )
387
+        );
388
+
389
+    }
390
+
391
+    /**
392
+     * Prepares refunded item counts.
393
+     *
394
+     * @return array.
395
+     */
396
+    protected function count_refunded_items() {
397
+
398
+        return (int) GetPaid_Reports_Helper::get_invoice_report_data(
399
+            array(
400
+                'data'         => array(
401
+                    'quantity'      => array(
402
+                        'type'            => 'invoice_item',
403
+                        'function'        => 'SUM',
404
+                        'name'            => 'invoice_item_count',
405
+                    ),
406
+                ),
407
+                'query_type'     => 'get_var',
408
+                'filter_range'   => $this->report_range,
409
+                'invoice_status' => array( 'wpi-refunded' ),
410
+            )
411
+        );
412
+
413
+    }
414
+
415
+    /**
416
+     * Prepares daily invoice totals.
417
+     *
418
+     * @return array.
419
+     */
420
+    protected function query_invoice_totals() {
421
+
422
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
423
+            array(
424
+                'data'         => array(
425
+                    'total'      => array(
426
+                        'type'            => 'invoice_data',
427
+                        'function'        => 'SUM',
428
+                        'name'            => 'total_sales',
429
+                    ),
430
+                    'tax'      => array(
431
+                        'type'            => 'invoice_data',
432
+                        'function'        => 'SUM',
433
+                        'name'            => 'total_tax',
434
+                    ),
435
+                    'discount'      => array(
436
+                        'type'            => 'invoice_data',
437
+                        'function'        => 'SUM',
438
+                        'name'            => 'total_discount',
439
+                    ),
440
+                    'fees_total'      => array(
441
+                        'type'            => 'invoice_data',
442
+                        'function'        => 'SUM',
443
+                        'name'            => 'total_fees',
444
+                    ),
445
+                    'subtotal'      => array(
446
+                        'type'            => 'invoice_data',
447
+                        'function'        => 'SUM',
448
+                        'name'            => 'subtotal',
449
+                    ),
450
+                    'post_date' => array(
451
+                        'type'     => 'post_data',
452
+                        'function' => '',
453
+                        'name'     => 'post_date',
454
+                    ),
455
+                ),
456
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
457
+                'order_by'       => 'post_date ASC',
458
+                'query_type'     => 'get_results',
459
+                'filter_range'   => $this->report_range,
460
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-renewal' ),
461
+            )
462
+        );
463
+
464
+    }
465
+
466
+    /**
467
+     * Prepares daily invoice totals.
468
+     *
469
+     * @return array.
470
+     */
471
+    protected function query_refunded_totals() {
472
+
473
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
474
+            array(
475
+                'data'         => array(
476
+                    'total'      => array(
477
+                        'type'            => 'invoice_data',
478
+                        'function'        => 'SUM',
479
+                        'name'            => 'total_sales',
480
+                    ),
481
+                    'tax'      => array(
482
+                        'type'            => 'invoice_data',
483
+                        'function'        => 'SUM',
484
+                        'name'            => 'total_tax',
485
+                    ),
486
+                    'discount'      => array(
487
+                        'type'            => 'invoice_data',
488
+                        'function'        => 'SUM',
489
+                        'name'            => 'total_discount',
490
+                    ),
491
+                    'fees_total'      => array(
492
+                        'type'            => 'invoice_data',
493
+                        'function'        => 'SUM',
494
+                        'name'            => 'total_fees',
495
+                    ),
496
+                    'subtotal'      => array(
497
+                        'type'            => 'invoice_data',
498
+                        'function'        => 'SUM',
499
+                        'name'            => 'subtotal',
500
+                    ),
501
+                    'post_date' => array(
502
+                        'type'     => 'post_data',
503
+                        'function' => '',
504
+                        'name'     => 'post_date',
505
+                    ),
506
+                ),
507
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
508
+                'order_by'       => 'post_date ASC',
509
+                'query_type'     => 'get_results',
510
+                'filter_range'   => $this->report_range,
511
+                'invoice_status' => array( 'wpi-refunded' ),
512
+            )
513
+        );
514
+
515
+    }
516
+
517
+    /**
518
+     * Get the Report's schema, conforming to JSON Schema.
519
+     *
520
+     * @return array
521
+     */
522
+    public function get_item_schema() {
523
+
524
+        $schema = array(
525
+            '$schema'    => 'http://json-schema.org/draft-04/schema#',
526
+            'title'      => 'sales_report',
527
+            'type'       => 'object',
528
+            'properties' => array(
529
+                'total_sales' => array(
530
+                    'description' => __( 'Gross sales in the period.', 'invoicing' ),
531
+                    'type'        => 'string',
532
+                    'context'     => array( 'view' ),
533
+                    'readonly'    => true,
534
+                ),
535
+                'net_sales' => array(
536
+                    'description' => __( 'Net sales in the period.', 'invoicing' ),
537
+                    'type'        => 'string',
538
+                    'context'     => array( 'view' ),
539
+                    'readonly'    => true,
540
+                ),
541
+                'average_sales' => array(
542
+                    'description' => __( 'Average net daily sales.', 'invoicing' ),
543
+                    'type'        => 'string',
544
+                    'context'     => array( 'view' ),
545
+                    'readonly'    => true,
546
+                ),
547
+                'average_total_sales' => array(
548
+                    'description' => __( 'Average gross daily sales.', 'invoicing' ),
549
+                    'type'        => 'string',
550
+                    'context'     => array( 'view' ),
551
+                    'readonly'    => true,
552
+                ),
553
+                'total_invoices'  => array(
554
+                    'description' => __( 'Number of paid invoices.', 'invoicing' ),
555
+                    'type'        => 'integer',
556
+                    'context'     => array( 'view' ),
557
+                    'readonly'    => true,
558
+                ),
559
+                'total_items' => array(
560
+                    'description' => __( 'Number of items purchased.', 'invoicing' ),
561
+                    'type'        => 'integer',
562
+                    'context'     => array( 'view' ),
563
+                    'readonly'    => true,
564
+                ),
565
+                'refunded_items' => array(
566
+                    'description' => __( 'Number of items refunded.', 'invoicing' ),
567
+                    'type'        => 'integer',
568
+                    'context'     => array( 'view' ),
569
+                    'readonly'    => true,
570
+                ),
571
+                'total_tax' => array(
572
+                    'description' => __( 'Total charged for taxes.', 'invoicing' ),
573
+                    'type'        => 'string',
574
+                    'context'     => array( 'view' ),
575
+                    'readonly'    => true,
576
+                ),
577
+                'total_refunded_tax' => array(
578
+                    'description' => __( 'Total refunded for taxes.', 'invoicing' ),
579
+                    'type'        => 'string',
580
+                    'context'     => array( 'view' ),
581
+                    'readonly'    => true,
582
+                ),
583
+                'total_fees' => array(
584
+                    'description' => __( 'Total fees charged.', 'invoicing' ),
585
+                    'type'        => 'string',
586
+                    'context'     => array( 'view' ),
587
+                    'readonly'    => true,
588
+                ),
589
+                'total_refunds' => array(
590
+                    'description' => __( 'Total of refunded invoices.', 'invoicing' ),
591
+                    'type'        => 'integer',
592
+                    'context'     => array( 'view' ),
593
+                    'readonly'    => true,
594
+                ),
595
+                'net_refunds' => array(
596
+                    'description' => __( 'Net of refunded invoices.', 'invoicing' ),
597
+                    'type'        => 'integer',
598
+                    'context'     => array( 'view' ),
599
+                    'readonly'    => true,
600
+                ),
601
+                'total_discount' => array(
602
+                    'description' => __( 'Total of discounts used.', 'invoicing' ),
603
+                    'type'        => 'integer',
604
+                    'context'     => array( 'view' ),
605
+                    'readonly'    => true,
606
+                ),
607
+                'totals' => array(
608
+                    'description' => __( 'Totals.', 'invoicing' ),
609
+                    'type'        => 'array',
610
+                    'items'       => array(
611
+                        'type'    => 'array',
612
+                    ),
613
+                    'context'     => array( 'view' ),
614
+                    'readonly'    => true,
615
+                ),
616
+                'interval' => array(
617
+                    'description' => __( 'Number of months/days in the report period.', 'invoicing' ),
618
+                    'type'        => 'integer',
619
+                    'context'     => array( 'view' ),
620
+                    'readonly'    => true,
621
+                ),
622
+                'previous_range'  => array(
623
+                    'description' => __( 'The previous report period.', 'invoicing' ),
624
+                    'type'        => 'array',
625
+                    'items'       => array(
626
+                        'type'    => 'string',
627
+                    ),
628
+                    'context'     => array( 'view' ),
629
+                    'readonly'    => true,
630
+                ),
631
+                'grouped_by' => array(
632
+                    'description' => __( 'The period used to group the totals.', 'invoicing' ),
633
+                    'type'        => 'string',
634
+                    'context'     => array( 'view' ),
635
+                    'enum'        => array( 'day', 'month' ),
636
+                    'readonly'    => true,
637
+                ),
638
+                'currency' => array(
639
+                    'description' => __( 'The default store currency.', 'invoicing' ),
640
+                    'type'        => 'string',
641
+                    'context'     => array( 'view' ),
642
+                    'readonly'    => true,
643
+                ),
644
+                'currency_symbol' => array(
645
+                    'description' => __( 'The default store currency symbol.', 'invoicing' ),
646
+                    'type'        => 'string',
647
+                    'context'     => array( 'view' ),
648
+                    'readonly'    => true,
649
+                ),
650
+                'currency_position' => array(
651
+                    'description' => __( 'The default store currency position.', 'invoicing' ),
652
+                    'type'        => 'string',
653
+                    'context'     => array( 'view' ),
654
+                    'readonly'    => true,
655
+                ),
656
+                'decimal_places' => array(
657
+                    'description' => __( 'The default store decimal places.', 'invoicing' ),
658
+                    'type'        => 'string',
659
+                    'context'     => array( 'view' ),
660
+                    'readonly'    => true,
661
+                ),
662
+                'thousands_sep' => array(
663
+                    'description' => __( 'The default store thousands separator.', 'invoicing' ),
664
+                    'type'        => 'string',
665
+                    'context'     => array( 'view' ),
666
+                    'readonly'    => true,
667
+                ),
668
+                'decimals_sep' => array(
669
+                    'description' => __( 'The default store decimals separator.', 'invoicing' ),
670
+                    'type'        => 'string',
671
+                    'context'     => array( 'view' ),
672
+                    'readonly'    => true,
673
+                ),
674
+            ),
675
+        );
676
+
677
+        return $this->add_additional_fields_schema( $schema );
678
+
679
+    }
680 680
 
681 681
 }
Please login to merge, or discard this patch.