Passed
Push — master ( 0d5a04...8eea4e )
by Brian
05:10
created
includes/reports/class-getpaid-reports-helper.php 1 patch
Indentation   +276 added lines, -276 removed lines patch added patch discarded remove patch
@@ -12,294 +12,294 @@
 block discarded – undo
12 12
  */
13 13
 class GetPaid_Reports_Helper {
14 14
 
15
-	/**
16
-	 * Get report totals such as invoice totals and discount amounts.
17
-	 *
18
-	 * Data example:
19
-	 *
20
-	 * 'subtotal' => array(
21
-	 *     'type'     => 'invoice_data',
22
-	 *     'function' => 'SUM',
23
-	 *     'name'     => 'subtotal'
24
-	 * )
25
-	 *
26
-	 * @param  array $args
27
-	 * @return mixed depending on query_type
28
-	 */
29
-	public static function get_invoice_report_data( $args = array() ) {
30
-		global $wpdb;
31
-
32
-		$default_args = array(
33
-			'data'                  => array(), // The data to retrieve.
34
-			'where'                 => array(), // An array of where queries.
35
-			'query_type'            => 'get_row', // wpdb query to run.
36
-			'group_by'              => '', // What to group results by.
37
-			'order_by'              => '', // What to order by.
38
-			'limit'                 => '', // Results limit.
39
-			'filter_range'          => array(), // An array of before and after dates to limit results by.
40
-			'invoice_types'         => array( 'wpi_invoice' ), // An array of post types to retrieve.
41
-			'invoice_status'        => array( 'publish', 'wpi-processing', 'wpi-onhold' ),
42
-			'parent_invoice_status' => false, // Optionally filter by parent invoice status.
43
-		);
44
-
45
-		$args         = apply_filters( 'getpaid_reports_get_invoice_report_data_args', $args );
46
-		$args         = wp_parse_args( $args, $default_args );
47
-
48
-		extract( $args );
49
-
50
-		if ( empty( $data ) ) {
51
-			return '';
52
-		}
53
-
54
-		$query           = array();
55
-		$query['select'] = 'SELECT ' . implode( ',', self::prepare_invoice_data( $data ) );
56
-		$query['from']   = "FROM {$wpdb->posts} AS posts";
57
-		$query['join']   = implode( ' ', self::prepare_invoice_joins( $data + $where, ! empty( $parent_invoice_status ) ) );
58
-
59
-		$query['where']  = "
15
+    /**
16
+     * Get report totals such as invoice totals and discount amounts.
17
+     *
18
+     * Data example:
19
+     *
20
+     * 'subtotal' => array(
21
+     *     'type'     => 'invoice_data',
22
+     *     'function' => 'SUM',
23
+     *     'name'     => 'subtotal'
24
+     * )
25
+     *
26
+     * @param  array $args
27
+     * @return mixed depending on query_type
28
+     */
29
+    public static function get_invoice_report_data( $args = array() ) {
30
+        global $wpdb;
31
+
32
+        $default_args = array(
33
+            'data'                  => array(), // The data to retrieve.
34
+            'where'                 => array(), // An array of where queries.
35
+            'query_type'            => 'get_row', // wpdb query to run.
36
+            'group_by'              => '', // What to group results by.
37
+            'order_by'              => '', // What to order by.
38
+            'limit'                 => '', // Results limit.
39
+            'filter_range'          => array(), // An array of before and after dates to limit results by.
40
+            'invoice_types'         => array( 'wpi_invoice' ), // An array of post types to retrieve.
41
+            'invoice_status'        => array( 'publish', 'wpi-processing', 'wpi-onhold' ),
42
+            'parent_invoice_status' => false, // Optionally filter by parent invoice status.
43
+        );
44
+
45
+        $args         = apply_filters( 'getpaid_reports_get_invoice_report_data_args', $args );
46
+        $args         = wp_parse_args( $args, $default_args );
47
+
48
+        extract( $args );
49
+
50
+        if ( empty( $data ) ) {
51
+            return '';
52
+        }
53
+
54
+        $query           = array();
55
+        $query['select'] = 'SELECT ' . implode( ',', self::prepare_invoice_data( $data ) );
56
+        $query['from']   = "FROM {$wpdb->posts} AS posts";
57
+        $query['join']   = implode( ' ', self::prepare_invoice_joins( $data + $where, ! empty( $parent_invoice_status ) ) );
58
+
59
+        $query['where']  = "
60 60
 			WHERE 	posts.post_type 	IN ( '" . implode( "','", $invoice_types ) . "' )
61 61
 			";
62 62
 
63
-		if ( ! empty( $invoice_status ) ) {
64
-			$query['where'] .= "
63
+        if ( ! empty( $invoice_status ) ) {
64
+            $query['where'] .= "
65 65
 				AND 	posts.post_status 	IN ( '" . implode( "','", $invoice_status ) . "' )
66 66
 			";
67
-		}
68
-
69
-		if ( ! empty( $parent_invoice_status ) ) {
70
-			if ( ! empty( $invoice_status ) ) {
71
-				$query['where'] .= " AND ( parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) OR parent.ID IS NULL ) ";
72
-			} else {
73
-				$query['where'] .= " AND parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) ";
74
-			}
75
-		}
76
-
77
-		if ( ! empty( $filter_range['before'] ) ) {
78
-			$query['where'] .= "
67
+        }
68
+
69
+        if ( ! empty( $parent_invoice_status ) ) {
70
+            if ( ! empty( $invoice_status ) ) {
71
+                $query['where'] .= " AND ( parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) OR parent.ID IS NULL ) ";
72
+            } else {
73
+                $query['where'] .= " AND parent.post_status IN ( '" . implode( "','", $parent_invoice_status ) . "' ) ";
74
+            }
75
+        }
76
+
77
+        if ( ! empty( $filter_range['before'] ) ) {
78
+            $query['where'] .= "
79 79
 				AND 	posts.post_date < '" . date( 'Y-m-d H:i:s', strtotime( $filter_range['before'] ) ) . "'
80 80
 			";
81
-		}
81
+        }
82 82
 
83
-		if ( ! empty( $filter_range['after'] ) ) {
84
-			$query['where'] .= "
83
+        if ( ! empty( $filter_range['after'] ) ) {
84
+            $query['where'] .= "
85 85
 				AND 	posts.post_date > '" . date( 'Y-m-d H:i:s', strtotime( $filter_range['after'] ) ) . "'
86 86
 			";
87
-		}
87
+        }
88 88
 
89
-		if ( ! empty( $where ) ) {
89
+        if ( ! empty( $where ) ) {
90 90
 
91
-			foreach ( $where as $value ) {
91
+            foreach ( $where as $value ) {
92 92
 
93
-				if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) {
94
-
95
-					if ( is_array( $value['value'] ) ) {
96
-						$value['value'] = implode( "','", $value['value'] );
97
-					}
98
-
99
-					if ( ! empty( $value['value'] ) ) {
100
-						$where_value = "{$value['operator']} ('{$value['value']}')";
101
-					}
102
-				} else {
103
-					$where_value = "{$value['operator']} '{$value['value']}'";
104
-				}
105
-
106
-				if ( ! empty( $where_value ) ) {
107
-					$query['where'] .= " AND {$value['key']} {$where_value}";
108
-				}
109
-			}
110
-		}
111
-
112
-		if ( $group_by ) {
113
-			$query['group_by'] = "GROUP BY {$group_by}";
114
-		}
115
-
116
-		if ( $order_by ) {
117
-			$query['order_by'] = "ORDER BY {$order_by}";
118
-		}
119
-
120
-		if ( $limit ) {
121
-			$query['limit'] = "LIMIT {$limit}";
122
-		}
123
-
124
-		$query = apply_filters( 'getpaid_reports_get_invoice_report_query', $query, $data );
125
-		$query = implode( ' ', $query );
126
-
127
-		return self::execute( $query_type, $query );
128
-
129
-	}
130
-
131
-	/**
132
-	 * Prepares the data to select.
133
-	 *
134
-	 *
135
-	 * @param  array $data
136
-	 * @return array
137
-	 */
138
-	public static function prepare_invoice_data( $data ) {
139
-
140
-		$prepared = array();
141
-
142
-		foreach ( $data as $raw_key => $value ) {
143
-			$key      = sanitize_key( $raw_key );
144
-			$distinct = '';
145
-
146
-			if ( isset( $value['distinct'] ) ) {
147
-				$distinct = 'DISTINCT';
148
-			}
149
-
150
-			$get_key = self::get_invoice_table_key( $key, $value['type'] );
151
-
152
-			if ( false === $get_key ) {
153
-				// Skip to the next foreach iteration else the query will be invalid.
154
-				continue;
155
-			}
156
-
157
-			if ( ! empty( $value['function'] ) ) {
158
-				$get = "{$value['function']}({$distinct} {$get_key})";
159
-			} else {
160
-				$get = "{$distinct} {$get_key}";
161
-			}
162
-
163
-			$prepared[] = "{$get} as {$value['name']}";
164
-		}
165
-
166
-		return $prepared;
167
-
168
-	}
169
-
170
-	/**
171
-	 * Prepares the joins to use.
172
-	 *
173
-	 *
174
-	 * @param  array $data
175
-	 * @param  bool $with_parent
176
-	 * @return array
177
-	 */
178
-	public static function prepare_invoice_joins( $data, $with_parent ) {
179
-		global $wpdb;
180
-
181
-		$prepared = array();
182
-
183
-		foreach ( $data as $raw_key => $value ) {
184
-			$join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER';
185
-			$type      = isset( $value['type'] ) ? $value['type'] : false;
186
-			$key       = sanitize_key( $raw_key );
187
-
188
-			switch ( $type ) {
189
-				case 'meta':
190
-					$prepared[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$raw_key}' )";
191
-					break;
192
-				case 'parent_meta':
193
-					$prepared[ "parent_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS parent_meta_{$key} ON (posts.post_parent = parent_meta_{$key}.post_id) AND (parent_meta_{$key}.meta_key = '{$raw_key}')";
194
-					break;
195
-				case 'invoice_data':
196
-					$prepared['invoices'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoices AS invoices ON posts.ID = invoices.post_id";
197
-					break;
198
-				case 'invoice_item':
199
-					$prepared['invoice_items'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoice_items AS invoice_items ON posts.ID = invoice_items.post_id";
200
-					break;
201
-			}
202
-		}
203
-
204
-		if ( $with_parent ) {
205
-			$prepared['parent'] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID";
206
-		}
207
-
208
-		return $prepared;
209
-
210
-	}
211
-
212
-	/**
213
-	 * Retrieves the appropriate table key to use.
214
-	 *
215
-	 *
216
-	 * @param  string $key
217
-	 * @param  string $table
218
-	 * @return string|false
219
-	 */
220
-	public static function get_invoice_table_key( $key, $table ) {
221
-
222
-		$keys = array(
223
-			'meta'         => "meta_{$key}.meta_value",
224
-			'parent_meta'  => "parent_meta_{$key}.meta_value",
225
-			'post_data'    => "posts.{$key}",
226
-			'invoice_data' => "invoices.{$key}",
227
-			'invoice_item' => "invoice_items.{$key}",
228
-		);
229
-
230
-		return isset( $keys[ $table ] ) ? $keys[ $table ] : false;
231
-
232
-	}
233
-
234
-	/**
235
-	 * Executes a query and caches the result for a minute.
236
-	 *
237
-	 *
238
-	 * @param  string $query_type
239
-	 * @param  string $query
240
-	 * @return mixed depending on query_type
241
-	 */
242
-	public static function execute( $query_type, $query ) {
243
-		global $wpdb;
244
-
245
-		$query_hash = md5( $query_type . $query );
246
-		$result     = self::get_cached_query( $query_hash );
247
-		if ( $result === false ) {
248
-			self::enable_big_selects();
249
-
250
-			$result = $wpdb->$query_type( $query );
251
-			self::set_cached_query( $query_hash, $result );
252
-		}
253
-
254
-		return $result;
255
-
256
-	}
257
-
258
-	/**
259
-	 * Enables big mysql selects for reports, just once for this session.
260
-	 */
261
-	protected static function enable_big_selects() {
262
-		static $big_selects = false;
263
-
264
-		global $wpdb;
265
-
266
-		if ( ! $big_selects ) {
267
-			$wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' );
268
-			$big_selects = true;
269
-		}
270
-	}
271
-
272
-	/**
273
-	 * Get the cached query result or null if it's not in the cache.
274
-	 *
275
-	 * @param string $query_hash The query hash.
276
-	 *
277
-	 * @return mixed|false The cache contents on success, false on failure to retrieve contents.
278
-	 */
279
-	protected static function get_cached_query( $query_hash ) {
280
-
281
-		return wp_cache_get(
282
-			$query_hash,
283
-			strtolower( __CLASS__ )
284
-		);
285
-
286
-	}
287
-
288
-	/**
289
-	 * Set the cached query result.
290
-	 *
291
-	 * @param string $query_hash The query hash.
292
-	 * @param mixed  $data The data to cache.
293
-	 */
294
-	protected static function set_cached_query( $query_hash, $data ) {
295
-
296
-		wp_cache_set(
297
-			$query_hash,
298
-			$data,
299
-			strtolower( __CLASS__ ),
300
-			5 * MINUTE_IN_SECONDS
301
-		);
302
-
303
-	}
93
+                if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) {
94
+
95
+                    if ( is_array( $value['value'] ) ) {
96
+                        $value['value'] = implode( "','", $value['value'] );
97
+                    }
98
+
99
+                    if ( ! empty( $value['value'] ) ) {
100
+                        $where_value = "{$value['operator']} ('{$value['value']}')";
101
+                    }
102
+                } else {
103
+                    $where_value = "{$value['operator']} '{$value['value']}'";
104
+                }
105
+
106
+                if ( ! empty( $where_value ) ) {
107
+                    $query['where'] .= " AND {$value['key']} {$where_value}";
108
+                }
109
+            }
110
+        }
111
+
112
+        if ( $group_by ) {
113
+            $query['group_by'] = "GROUP BY {$group_by}";
114
+        }
115
+
116
+        if ( $order_by ) {
117
+            $query['order_by'] = "ORDER BY {$order_by}";
118
+        }
119
+
120
+        if ( $limit ) {
121
+            $query['limit'] = "LIMIT {$limit}";
122
+        }
123
+
124
+        $query = apply_filters( 'getpaid_reports_get_invoice_report_query', $query, $data );
125
+        $query = implode( ' ', $query );
126
+
127
+        return self::execute( $query_type, $query );
128
+
129
+    }
130
+
131
+    /**
132
+     * Prepares the data to select.
133
+     *
134
+     *
135
+     * @param  array $data
136
+     * @return array
137
+     */
138
+    public static function prepare_invoice_data( $data ) {
139
+
140
+        $prepared = array();
141
+
142
+        foreach ( $data as $raw_key => $value ) {
143
+            $key      = sanitize_key( $raw_key );
144
+            $distinct = '';
145
+
146
+            if ( isset( $value['distinct'] ) ) {
147
+                $distinct = 'DISTINCT';
148
+            }
149
+
150
+            $get_key = self::get_invoice_table_key( $key, $value['type'] );
151
+
152
+            if ( false === $get_key ) {
153
+                // Skip to the next foreach iteration else the query will be invalid.
154
+                continue;
155
+            }
156
+
157
+            if ( ! empty( $value['function'] ) ) {
158
+                $get = "{$value['function']}({$distinct} {$get_key})";
159
+            } else {
160
+                $get = "{$distinct} {$get_key}";
161
+            }
162
+
163
+            $prepared[] = "{$get} as {$value['name']}";
164
+        }
165
+
166
+        return $prepared;
167
+
168
+    }
169
+
170
+    /**
171
+     * Prepares the joins to use.
172
+     *
173
+     *
174
+     * @param  array $data
175
+     * @param  bool $with_parent
176
+     * @return array
177
+     */
178
+    public static function prepare_invoice_joins( $data, $with_parent ) {
179
+        global $wpdb;
180
+
181
+        $prepared = array();
182
+
183
+        foreach ( $data as $raw_key => $value ) {
184
+            $join_type = isset( $value['join_type'] ) ? $value['join_type'] : 'INNER';
185
+            $type      = isset( $value['type'] ) ? $value['type'] : false;
186
+            $key       = sanitize_key( $raw_key );
187
+
188
+            switch ( $type ) {
189
+                case 'meta':
190
+                    $prepared[ "meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS meta_{$key} ON ( posts.ID = meta_{$key}.post_id AND meta_{$key}.meta_key = '{$raw_key}' )";
191
+                    break;
192
+                case 'parent_meta':
193
+                    $prepared[ "parent_meta_{$key}" ] = "{$join_type} JOIN {$wpdb->postmeta} AS parent_meta_{$key} ON (posts.post_parent = parent_meta_{$key}.post_id) AND (parent_meta_{$key}.meta_key = '{$raw_key}')";
194
+                    break;
195
+                case 'invoice_data':
196
+                    $prepared['invoices'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoices AS invoices ON posts.ID = invoices.post_id";
197
+                    break;
198
+                case 'invoice_item':
199
+                    $prepared['invoice_items'] = "{$join_type} JOIN {$wpdb->prefix}getpaid_invoice_items AS invoice_items ON posts.ID = invoice_items.post_id";
200
+                    break;
201
+            }
202
+        }
203
+
204
+        if ( $with_parent ) {
205
+            $prepared['parent'] = "LEFT JOIN {$wpdb->posts} AS parent ON posts.post_parent = parent.ID";
206
+        }
207
+
208
+        return $prepared;
209
+
210
+    }
211
+
212
+    /**
213
+     * Retrieves the appropriate table key to use.
214
+     *
215
+     *
216
+     * @param  string $key
217
+     * @param  string $table
218
+     * @return string|false
219
+     */
220
+    public static function get_invoice_table_key( $key, $table ) {
221
+
222
+        $keys = array(
223
+            'meta'         => "meta_{$key}.meta_value",
224
+            'parent_meta'  => "parent_meta_{$key}.meta_value",
225
+            'post_data'    => "posts.{$key}",
226
+            'invoice_data' => "invoices.{$key}",
227
+            'invoice_item' => "invoice_items.{$key}",
228
+        );
229
+
230
+        return isset( $keys[ $table ] ) ? $keys[ $table ] : false;
231
+
232
+    }
233
+
234
+    /**
235
+     * Executes a query and caches the result for a minute.
236
+     *
237
+     *
238
+     * @param  string $query_type
239
+     * @param  string $query
240
+     * @return mixed depending on query_type
241
+     */
242
+    public static function execute( $query_type, $query ) {
243
+        global $wpdb;
244
+
245
+        $query_hash = md5( $query_type . $query );
246
+        $result     = self::get_cached_query( $query_hash );
247
+        if ( $result === false ) {
248
+            self::enable_big_selects();
249
+
250
+            $result = $wpdb->$query_type( $query );
251
+            self::set_cached_query( $query_hash, $result );
252
+        }
253
+
254
+        return $result;
255
+
256
+    }
257
+
258
+    /**
259
+     * Enables big mysql selects for reports, just once for this session.
260
+     */
261
+    protected static function enable_big_selects() {
262
+        static $big_selects = false;
263
+
264
+        global $wpdb;
265
+
266
+        if ( ! $big_selects ) {
267
+            $wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' );
268
+            $big_selects = true;
269
+        }
270
+    }
271
+
272
+    /**
273
+     * Get the cached query result or null if it's not in the cache.
274
+     *
275
+     * @param string $query_hash The query hash.
276
+     *
277
+     * @return mixed|false The cache contents on success, false on failure to retrieve contents.
278
+     */
279
+    protected static function get_cached_query( $query_hash ) {
280
+
281
+        return wp_cache_get(
282
+            $query_hash,
283
+            strtolower( __CLASS__ )
284
+        );
285
+
286
+    }
287
+
288
+    /**
289
+     * Set the cached query result.
290
+     *
291
+     * @param string $query_hash The query hash.
292
+     * @param mixed  $data The data to cache.
293
+     */
294
+    protected static function set_cached_query( $query_hash, $data ) {
295
+
296
+        wp_cache_set(
297
+            $query_hash,
298
+            $data,
299
+            strtolower( __CLASS__ ),
300
+            5 * MINUTE_IN_SECONDS
301
+        );
302
+
303
+    }
304 304
 
305 305
 }
Please login to merge, or discard this patch.
includes/api/class-getpaid-rest-report-sales-controller.php 1 patch
Indentation   +647 added lines, -647 removed lines patch added patch discarded remove patch
@@ -18,652 +18,652 @@
 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        = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS ) );
218
-		$report_data->end_date          = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['before'] ) - DAY_IN_SECONDS ) );
219
-		$report_data->decimals_sep      = wpinv_decimal_separator();
220
-
221
-		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
222
-		$data    = $report_data;
223
-		unset( $data->invoice_counts, $data->invoices, $data->coupons, $data->refunds, $data->invoice_items );
224
-		$data    = $this->add_additional_fields_to_object( $data, $request );
225
-		$data    = $this->filter_response_by_context( $data, $context );
226
-
227
-		// Wrap the data in a response object.
228
-		$response = rest_ensure_response( $data );
229
-		$response->add_links( array(
230
-			'about' => array(
231
-				'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
232
-			),
233
-		) );
234
-
235
-		return apply_filters( 'getpaid_rest_prepare_report_sales', $response, $report_data, $request );
236
-	}
237
-
238
-	/**
239
-	 * Get report data.
240
-	 *
241
-	 * @return stdClass
242
-	 */
243
-	public function get_report_data() {
244
-		if ( empty( $this->report_data ) ) {
245
-			$this->query_report_data();
246
-		}
247
-		return $this->report_data;
248
-	}
249
-
250
-	/**
251
-	 * Get all data needed for this report and store in the class.
252
-	 */
253
-	protected function query_report_data() {
254
-
255
-		// Prepare reports.
256
-		$this->report_data = (object) array(
257
-			'invoice_counts' => $this->query_invoice_counts(),//count, post_date
258
-			'coupons'        => $this->query_coupon_counts(), // discount_amount, post_date
259
-			'invoice_items'  => $this->query_item_counts(), // invoice_item_count, post_date
260
-			'refunded_items' => $this->count_refunded_items(), // invoice_item_count, post_date
261
-			'invoices'       => $this->query_invoice_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
262
-			'refunds'        => $this->query_refunded_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
263
-		);
264
-
265
-		// Calculated totals.
266
-		$this->report_data->total_tax          = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_tax' ) ) );
267
-		$this->report_data->total_sales        = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_sales' ) ) );
268
-		$this->report_data->total_discount     = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_discount' ) ) );
269
-		$this->report_data->total_fees         = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_fees' ) ) );
270
-		$this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'subtotal' ) ) );
271
-		$this->report_data->net_sales          = wpinv_round_amount( $this->report_data->total_sales - max( 0, $this->report_data->total_tax ) );
272
-		$this->report_data->total_refunded_tax = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_tax' ) ) );
273
-		$this->report_data->total_refunds      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_sales' ) ) );
274
-		$this->report_data->refunded_discount  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_discount' ) ) );
275
-		$this->report_data->refunded_fees      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_fees' ) ) );
276
-		$this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'subtotal' ) ) );
277
-		$this->report_data->net_refunds        = wpinv_round_amount( $this->report_data->total_refunds + max( 0, $this->report_data->total_refunded_tax ) );
278
-
279
-
280
-		// Calculate average based on net.
281
-		$this->report_data->average_sales       = wpinv_round_amount( $this->report_data->net_sales / max( $this->interval, 1 ), 2 );
282
-		$this->report_data->average_total_sales = wpinv_round_amount( $this->report_data->total_sales / max( $this->interval, 1 ), 2 );
283
-
284
-		// Total invoices in this period, even if refunded.
285
-		$this->report_data->total_invoices = absint( array_sum( wp_list_pluck( $this->report_data->invoice_counts, 'count' ) ) );
286
-
287
-		// Items invoiced in this period, even if refunded.
288
-		$this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->invoice_items, 'invoice_item_count' ) ) );
289
-
290
-		// 3rd party filtering of report data
291
-		$this->report_data = apply_filters( 'getpaid_rest_api_filter_report_data', $this->report_data );
292
-	}
293
-
294
-	/**
295
-	 * Prepares invoice counts.
296
-	 *
297
-	 * @return array.
298
-	 */
299
-	protected function query_invoice_counts() {
300
-
301
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
302
-			array(
303
-				'data'         => array(
304
-					'ID'        => array(
305
-						'type'     => 'post_data',
306
-						'function' => 'COUNT',
307
-						'name'     => 'count',
308
-						'distinct' => true,
309
-					),
310
-					'post_date' => array(
311
-						'type'     => 'post_data',
312
-						'function' => '',
313
-						'name'     => 'post_date',
314
-					),
315
-				),
316
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
317
-				'order_by'       => 'post_date ASC',
318
-				'query_type'     => 'get_results',
319
-				'filter_range'   => $this->report_range,
320
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded' ),
321
-			)
322
-		);
323
-
324
-	}
325
-
326
-	/**
327
-	 * Prepares coupon counts.
328
-	 *
329
-	 * @return array.
330
-	 */
331
-	protected function query_coupon_counts() {
332
-
333
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
334
-			array(
335
-				'data'         => array(
336
-					'discount' => array(
337
-						'type'     => 'invoice_data',
338
-						'function' => 'SUM',
339
-						'name'     => 'discount_amount',
340
-					),
341
-					'post_date'       => array(
342
-						'type'     => 'post_data',
343
-						'function' => '',
344
-						'name'     => 'post_date',
345
-					),
346
-				),
347
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
348
-				'order_by'       => 'post_date ASC',
349
-				'query_type'     => 'get_results',
350
-				'filter_range'   => $this->report_range,
351
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded' ),
352
-			)
353
-		);
354
-
355
-	}
356
-
357
-	/**
358
-	 * Prepares item counts.
359
-	 *
360
-	 * @return array.
361
-	 */
362
-	protected function query_item_counts() {
363
-
364
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
365
-			array(
366
-				'data'         => array(
367
-					'quantity'      => array(
368
-						'type'            => 'invoice_item',
369
-						'function'        => 'SUM',
370
-						'name'            => 'invoice_item_count',
371
-					),
372
-					'post_date' => array(
373
-						'type'     => 'post_data',
374
-						'function' => '',
375
-						'name'     => 'post_date',
376
-					),
377
-				),
378
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
379
-				'order_by'       => 'post_date ASC',
380
-				'query_type'     => 'get_results',
381
-				'filter_range'   => $this->report_range,
382
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded' ),
383
-			)
384
-		);
385
-
386
-	}
387
-
388
-	/**
389
-	 * Prepares refunded item counts.
390
-	 *
391
-	 * @return array.
392
-	 */
393
-	protected function count_refunded_items() {
394
-
395
-		return (int) GetPaid_Reports_Helper::get_invoice_report_data(
396
-			array(
397
-				'data'         => array(
398
-					'quantity'      => array(
399
-						'type'            => 'invoice_item',
400
-						'function'        => 'SUM',
401
-						'name'            => 'invoice_item_count',
402
-					),
403
-				),
404
-				'query_type'     => 'get_var',
405
-				'filter_range'   => $this->report_range,
406
-				'invoice_status' => array( 'wpi-refunded' ),
407
-			)
408
-		);
409
-
410
-	}
411
-
412
-	/**
413
-	 * Prepares daily invoice totals.
414
-	 *
415
-	 * @return array.
416
-	 */
417
-	protected function query_invoice_totals() {
418
-
419
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
420
-			array(
421
-				'data'         => array(
422
-					'total'      => array(
423
-						'type'            => 'invoice_data',
424
-						'function'        => 'SUM',
425
-						'name'            => 'total_sales',
426
-					),
427
-					'tax'      => array(
428
-						'type'            => 'invoice_data',
429
-						'function'        => 'SUM',
430
-						'name'            => 'total_tax',
431
-					),
432
-					'discount'      => array(
433
-						'type'            => 'invoice_data',
434
-						'function'        => 'SUM',
435
-						'name'            => 'total_discount',
436
-					),
437
-					'fees_total'      => array(
438
-						'type'            => 'invoice_data',
439
-						'function'        => 'SUM',
440
-						'name'            => 'total_fees',
441
-					),
442
-					'subtotal'      => array(
443
-						'type'            => 'invoice_data',
444
-						'function'        => 'SUM',
445
-						'name'            => 'subtotal',
446
-					),
447
-					'post_date' => array(
448
-						'type'     => 'post_data',
449
-						'function' => '',
450
-						'name'     => 'post_date',
451
-					),
452
-				),
453
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
454
-				'order_by'       => 'post_date ASC',
455
-				'query_type'     => 'get_results',
456
-				'filter_range'   => $this->report_range,
457
-				'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold' ),
458
-			)
459
-		);
460
-
461
-	}
462
-
463
-	/**
464
-	 * Prepares daily invoice totals.
465
-	 *
466
-	 * @return array.
467
-	 */
468
-	protected function query_refunded_totals() {
469
-
470
-		return (array) GetPaid_Reports_Helper::get_invoice_report_data(
471
-			array(
472
-				'data'         => array(
473
-					'total'      => array(
474
-						'type'            => 'invoice_data',
475
-						'function'        => 'SUM',
476
-						'name'            => 'total_sales',
477
-					),
478
-					'tax'      => array(
479
-						'type'            => 'invoice_data',
480
-						'function'        => 'SUM',
481
-						'name'            => 'total_tax',
482
-					),
483
-					'discount'      => array(
484
-						'type'            => 'invoice_data',
485
-						'function'        => 'SUM',
486
-						'name'            => 'total_discount',
487
-					),
488
-					'fees_total'      => array(
489
-						'type'            => 'invoice_data',
490
-						'function'        => 'SUM',
491
-						'name'            => 'total_fees',
492
-					),
493
-					'subtotal'      => array(
494
-						'type'            => 'invoice_data',
495
-						'function'        => 'SUM',
496
-						'name'            => 'subtotal',
497
-					),
498
-					'post_date' => array(
499
-						'type'     => 'post_data',
500
-						'function' => '',
501
-						'name'     => 'post_date',
502
-					),
503
-				),
504
-				'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
505
-				'order_by'       => 'post_date ASC',
506
-				'query_type'     => 'get_results',
507
-				'filter_range'   => $this->report_range,
508
-				'invoice_status' => array( 'wpi-refunded' ),
509
-			)
510
-		);
511
-
512
-	}
513
-
514
-	/**
515
-	 * Get the Report's schema, conforming to JSON Schema.
516
-	 *
517
-	 * @return array
518
-	 */
519
-	public function get_item_schema() {
520
-
521
-		$schema = array(
522
-			'$schema'    => 'http://json-schema.org/draft-04/schema#',
523
-			'title'      => 'sales_report',
524
-			'type'       => 'object',
525
-			'properties' => array(
526
-				'total_sales' => array(
527
-					'description' => __( 'Gross sales in the period.', 'invoicing' ),
528
-					'type'        => 'string',
529
-					'context'     => array( 'view' ),
530
-					'readonly'    => true,
531
-				),
532
-				'net_sales' => array(
533
-					'description' => __( 'Net sales in the period.', 'invoicing' ),
534
-					'type'        => 'string',
535
-					'context'     => array( 'view' ),
536
-					'readonly'    => true,
537
-				),
538
-				'average_sales' => array(
539
-					'description' => __( 'Average net daily sales.', 'invoicing' ),
540
-					'type'        => 'string',
541
-					'context'     => array( 'view' ),
542
-					'readonly'    => true,
543
-				),
544
-				'average_total_sales' => array(
545
-					'description' => __( 'Average gross daily sales.', 'invoicing' ),
546
-					'type'        => 'string',
547
-					'context'     => array( 'view' ),
548
-					'readonly'    => true,
549
-				),
550
-				'total_invoices'  => array(
551
-					'description' => __( 'Number of paid invoices.', 'invoicing' ),
552
-					'type'        => 'integer',
553
-					'context'     => array( 'view' ),
554
-					'readonly'    => true,
555
-				),
556
-				'total_items' => array(
557
-					'description' => __( 'Number of items purchased.', 'invoicing' ),
558
-					'type'        => 'integer',
559
-					'context'     => array( 'view' ),
560
-					'readonly'    => true,
561
-				),
562
-				'refunded_items' => array(
563
-					'description' => __( 'Number of items refunded.', 'invoicing' ),
564
-					'type'        => 'integer',
565
-					'context'     => array( 'view' ),
566
-					'readonly'    => true,
567
-				),
568
-				'total_tax' => array(
569
-					'description' => __( 'Total charged for taxes.', 'invoicing' ),
570
-					'type'        => 'string',
571
-					'context'     => array( 'view' ),
572
-					'readonly'    => true,
573
-				),
574
-				'total_refunded_tax' => array(
575
-					'description' => __( 'Total refunded for taxes.', 'invoicing' ),
576
-					'type'        => 'string',
577
-					'context'     => array( 'view' ),
578
-					'readonly'    => true,
579
-				),
580
-				'total_fees' => array(
581
-					'description' => __( 'Total fees charged.', 'invoicing' ),
582
-					'type'        => 'string',
583
-					'context'     => array( 'view' ),
584
-					'readonly'    => true,
585
-				),
586
-				'total_refunds' => array(
587
-					'description' => __( 'Total of refunded invoices.', 'invoicing' ),
588
-					'type'        => 'integer',
589
-					'context'     => array( 'view' ),
590
-					'readonly'    => true,
591
-				),
592
-				'net_refunds' => array(
593
-					'description' => __( 'Net of refunded invoices.', 'invoicing' ),
594
-					'type'        => 'integer',
595
-					'context'     => array( 'view' ),
596
-					'readonly'    => true,
597
-				),
598
-				'total_discount' => array(
599
-					'description' => __( 'Total of discounts used.', 'invoicing' ),
600
-					'type'        => 'integer',
601
-					'context'     => array( 'view' ),
602
-					'readonly'    => true,
603
-				),
604
-				'totals' => array(
605
-					'description' => __( 'Totals.', 'invoicing' ),
606
-					'type'        => 'array',
607
-					'items'       => array(
608
-						'type'    => 'array',
609
-					),
610
-					'context'     => array( 'view' ),
611
-					'readonly'    => true,
612
-				),
613
-				'interval' => array(
614
-					'description' => __( 'Number of months/days in the report period.', 'invoicing' ),
615
-					'type'        => 'integer',
616
-					'context'     => array( 'view' ),
617
-					'readonly'    => true,
618
-				),
619
-				'grouped_by' => array(
620
-					'description' => __( 'The period used to group the totals.', 'invoicing' ),
621
-					'type'        => 'string',
622
-					'context'     => array( 'view' ),
623
-					'enum'        => array( 'day', 'month' ),
624
-					'readonly'    => true,
625
-				),
626
-				'currency' => array(
627
-					'description' => __( 'The default store currency.', 'invoicing' ),
628
-					'type'        => 'string',
629
-					'context'     => array( 'view' ),
630
-					'readonly'    => true,
631
-				),
632
-				'currency_symbol' => array(
633
-					'description' => __( 'The default store currency symbol.', 'invoicing' ),
634
-					'type'        => 'string',
635
-					'context'     => array( 'view' ),
636
-					'readonly'    => true,
637
-				),
638
-				'currency_position' => array(
639
-					'description' => __( 'The default store currency position.', 'invoicing' ),
640
-					'type'        => 'string',
641
-					'context'     => array( 'view' ),
642
-					'readonly'    => true,
643
-				),
644
-				'decimal_places' => array(
645
-					'description' => __( 'The default store decimal places.', 'invoicing' ),
646
-					'type'        => 'string',
647
-					'context'     => array( 'view' ),
648
-					'readonly'    => true,
649
-				),
650
-				'thousands_sep' => array(
651
-					'description' => __( 'The default store thousands separator.', 'invoicing' ),
652
-					'type'        => 'string',
653
-					'context'     => array( 'view' ),
654
-					'readonly'    => true,
655
-				),
656
-				'decimals_sep' => array(
657
-					'description' => __( 'The default store decimals separator.', 'invoicing' ),
658
-					'type'        => 'string',
659
-					'context'     => array( 'view' ),
660
-					'readonly'    => true,
661
-				),
662
-			),
663
-		);
664
-
665
-		return $this->add_additional_fields_schema( $schema );
666
-
667
-	}
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        = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['after'] ) + DAY_IN_SECONDS ) );
218
+        $report_data->end_date          = getpaid_format_date( date( 'Y-m-d', strtotime( $this->report_range['before'] ) - DAY_IN_SECONDS ) );
219
+        $report_data->decimals_sep      = wpinv_decimal_separator();
220
+
221
+        $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
222
+        $data    = $report_data;
223
+        unset( $data->invoice_counts, $data->invoices, $data->coupons, $data->refunds, $data->invoice_items );
224
+        $data    = $this->add_additional_fields_to_object( $data, $request );
225
+        $data    = $this->filter_response_by_context( $data, $context );
226
+
227
+        // Wrap the data in a response object.
228
+        $response = rest_ensure_response( $data );
229
+        $response->add_links( array(
230
+            'about' => array(
231
+                'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
232
+            ),
233
+        ) );
234
+
235
+        return apply_filters( 'getpaid_rest_prepare_report_sales', $response, $report_data, $request );
236
+    }
237
+
238
+    /**
239
+     * Get report data.
240
+     *
241
+     * @return stdClass
242
+     */
243
+    public function get_report_data() {
244
+        if ( empty( $this->report_data ) ) {
245
+            $this->query_report_data();
246
+        }
247
+        return $this->report_data;
248
+    }
249
+
250
+    /**
251
+     * Get all data needed for this report and store in the class.
252
+     */
253
+    protected function query_report_data() {
254
+
255
+        // Prepare reports.
256
+        $this->report_data = (object) array(
257
+            'invoice_counts' => $this->query_invoice_counts(),//count, post_date
258
+            'coupons'        => $this->query_coupon_counts(), // discount_amount, post_date
259
+            'invoice_items'  => $this->query_item_counts(), // invoice_item_count, post_date
260
+            'refunded_items' => $this->count_refunded_items(), // invoice_item_count, post_date
261
+            'invoices'       => $this->query_invoice_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
262
+            'refunds'        => $this->query_refunded_totals(), // total_sales, total_tax, total_discount, total_fees, subtotal, post_date
263
+        );
264
+
265
+        // Calculated totals.
266
+        $this->report_data->total_tax          = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_tax' ) ) );
267
+        $this->report_data->total_sales        = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_sales' ) ) );
268
+        $this->report_data->total_discount     = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_discount' ) ) );
269
+        $this->report_data->total_fees         = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'total_fees' ) ) );
270
+        $this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->invoices, 'subtotal' ) ) );
271
+        $this->report_data->net_sales          = wpinv_round_amount( $this->report_data->total_sales - max( 0, $this->report_data->total_tax ) );
272
+        $this->report_data->total_refunded_tax = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_tax' ) ) );
273
+        $this->report_data->total_refunds      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_sales' ) ) );
274
+        $this->report_data->refunded_discount  = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_discount' ) ) );
275
+        $this->report_data->refunded_fees      = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'total_fees' ) ) );
276
+        $this->report_data->subtotal           = wpinv_round_amount( array_sum( wp_list_pluck( $this->report_data->refunds, 'subtotal' ) ) );
277
+        $this->report_data->net_refunds        = wpinv_round_amount( $this->report_data->total_refunds + max( 0, $this->report_data->total_refunded_tax ) );
278
+
279
+
280
+        // Calculate average based on net.
281
+        $this->report_data->average_sales       = wpinv_round_amount( $this->report_data->net_sales / max( $this->interval, 1 ), 2 );
282
+        $this->report_data->average_total_sales = wpinv_round_amount( $this->report_data->total_sales / max( $this->interval, 1 ), 2 );
283
+
284
+        // Total invoices in this period, even if refunded.
285
+        $this->report_data->total_invoices = absint( array_sum( wp_list_pluck( $this->report_data->invoice_counts, 'count' ) ) );
286
+
287
+        // Items invoiced in this period, even if refunded.
288
+        $this->report_data->total_items = absint( array_sum( wp_list_pluck( $this->report_data->invoice_items, 'invoice_item_count' ) ) );
289
+
290
+        // 3rd party filtering of report data
291
+        $this->report_data = apply_filters( 'getpaid_rest_api_filter_report_data', $this->report_data );
292
+    }
293
+
294
+    /**
295
+     * Prepares invoice counts.
296
+     *
297
+     * @return array.
298
+     */
299
+    protected function query_invoice_counts() {
300
+
301
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
302
+            array(
303
+                'data'         => array(
304
+                    'ID'        => array(
305
+                        'type'     => 'post_data',
306
+                        'function' => 'COUNT',
307
+                        'name'     => 'count',
308
+                        'distinct' => true,
309
+                    ),
310
+                    'post_date' => array(
311
+                        'type'     => 'post_data',
312
+                        'function' => '',
313
+                        'name'     => 'post_date',
314
+                    ),
315
+                ),
316
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
317
+                'order_by'       => 'post_date ASC',
318
+                'query_type'     => 'get_results',
319
+                'filter_range'   => $this->report_range,
320
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded' ),
321
+            )
322
+        );
323
+
324
+    }
325
+
326
+    /**
327
+     * Prepares coupon counts.
328
+     *
329
+     * @return array.
330
+     */
331
+    protected function query_coupon_counts() {
332
+
333
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
334
+            array(
335
+                'data'         => array(
336
+                    'discount' => array(
337
+                        'type'     => 'invoice_data',
338
+                        'function' => 'SUM',
339
+                        'name'     => 'discount_amount',
340
+                    ),
341
+                    'post_date'       => array(
342
+                        'type'     => 'post_data',
343
+                        'function' => '',
344
+                        'name'     => 'post_date',
345
+                    ),
346
+                ),
347
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
348
+                'order_by'       => 'post_date ASC',
349
+                'query_type'     => 'get_results',
350
+                'filter_range'   => $this->report_range,
351
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded' ),
352
+            )
353
+        );
354
+
355
+    }
356
+
357
+    /**
358
+     * Prepares item counts.
359
+     *
360
+     * @return array.
361
+     */
362
+    protected function query_item_counts() {
363
+
364
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
365
+            array(
366
+                'data'         => array(
367
+                    'quantity'      => array(
368
+                        'type'            => 'invoice_item',
369
+                        'function'        => 'SUM',
370
+                        'name'            => 'invoice_item_count',
371
+                    ),
372
+                    'post_date' => array(
373
+                        'type'     => 'post_data',
374
+                        'function' => '',
375
+                        'name'     => 'post_date',
376
+                    ),
377
+                ),
378
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
379
+                'order_by'       => 'post_date ASC',
380
+                'query_type'     => 'get_results',
381
+                'filter_range'   => $this->report_range,
382
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold', 'wpi-refunded' ),
383
+            )
384
+        );
385
+
386
+    }
387
+
388
+    /**
389
+     * Prepares refunded item counts.
390
+     *
391
+     * @return array.
392
+     */
393
+    protected function count_refunded_items() {
394
+
395
+        return (int) GetPaid_Reports_Helper::get_invoice_report_data(
396
+            array(
397
+                'data'         => array(
398
+                    'quantity'      => array(
399
+                        'type'            => 'invoice_item',
400
+                        'function'        => 'SUM',
401
+                        'name'            => 'invoice_item_count',
402
+                    ),
403
+                ),
404
+                'query_type'     => 'get_var',
405
+                'filter_range'   => $this->report_range,
406
+                'invoice_status' => array( 'wpi-refunded' ),
407
+            )
408
+        );
409
+
410
+    }
411
+
412
+    /**
413
+     * Prepares daily invoice totals.
414
+     *
415
+     * @return array.
416
+     */
417
+    protected function query_invoice_totals() {
418
+
419
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
420
+            array(
421
+                'data'         => array(
422
+                    'total'      => array(
423
+                        'type'            => 'invoice_data',
424
+                        'function'        => 'SUM',
425
+                        'name'            => 'total_sales',
426
+                    ),
427
+                    'tax'      => array(
428
+                        'type'            => 'invoice_data',
429
+                        'function'        => 'SUM',
430
+                        'name'            => 'total_tax',
431
+                    ),
432
+                    'discount'      => array(
433
+                        'type'            => 'invoice_data',
434
+                        'function'        => 'SUM',
435
+                        'name'            => 'total_discount',
436
+                    ),
437
+                    'fees_total'      => array(
438
+                        'type'            => 'invoice_data',
439
+                        'function'        => 'SUM',
440
+                        'name'            => 'total_fees',
441
+                    ),
442
+                    'subtotal'      => array(
443
+                        'type'            => 'invoice_data',
444
+                        'function'        => 'SUM',
445
+                        'name'            => 'subtotal',
446
+                    ),
447
+                    'post_date' => array(
448
+                        'type'     => 'post_data',
449
+                        'function' => '',
450
+                        'name'     => 'post_date',
451
+                    ),
452
+                ),
453
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
454
+                'order_by'       => 'post_date ASC',
455
+                'query_type'     => 'get_results',
456
+                'filter_range'   => $this->report_range,
457
+                'invoice_status' => array( 'publish', 'wpi-processing', 'wpi-onhold' ),
458
+            )
459
+        );
460
+
461
+    }
462
+
463
+    /**
464
+     * Prepares daily invoice totals.
465
+     *
466
+     * @return array.
467
+     */
468
+    protected function query_refunded_totals() {
469
+
470
+        return (array) GetPaid_Reports_Helper::get_invoice_report_data(
471
+            array(
472
+                'data'         => array(
473
+                    'total'      => array(
474
+                        'type'            => 'invoice_data',
475
+                        'function'        => 'SUM',
476
+                        'name'            => 'total_sales',
477
+                    ),
478
+                    'tax'      => array(
479
+                        'type'            => 'invoice_data',
480
+                        'function'        => 'SUM',
481
+                        'name'            => 'total_tax',
482
+                    ),
483
+                    'discount'      => array(
484
+                        'type'            => 'invoice_data',
485
+                        'function'        => 'SUM',
486
+                        'name'            => 'total_discount',
487
+                    ),
488
+                    'fees_total'      => array(
489
+                        'type'            => 'invoice_data',
490
+                        'function'        => 'SUM',
491
+                        'name'            => 'total_fees',
492
+                    ),
493
+                    'subtotal'      => array(
494
+                        'type'            => 'invoice_data',
495
+                        'function'        => 'SUM',
496
+                        'name'            => 'subtotal',
497
+                    ),
498
+                    'post_date' => array(
499
+                        'type'     => 'post_data',
500
+                        'function' => '',
501
+                        'name'     => 'post_date',
502
+                    ),
503
+                ),
504
+                'group_by'       => $this->get_group_by_sql( 'posts.post_date' ),
505
+                'order_by'       => 'post_date ASC',
506
+                'query_type'     => 'get_results',
507
+                'filter_range'   => $this->report_range,
508
+                'invoice_status' => array( 'wpi-refunded' ),
509
+            )
510
+        );
511
+
512
+    }
513
+
514
+    /**
515
+     * Get the Report's schema, conforming to JSON Schema.
516
+     *
517
+     * @return array
518
+     */
519
+    public function get_item_schema() {
520
+
521
+        $schema = array(
522
+            '$schema'    => 'http://json-schema.org/draft-04/schema#',
523
+            'title'      => 'sales_report',
524
+            'type'       => 'object',
525
+            'properties' => array(
526
+                'total_sales' => array(
527
+                    'description' => __( 'Gross sales in the period.', 'invoicing' ),
528
+                    'type'        => 'string',
529
+                    'context'     => array( 'view' ),
530
+                    'readonly'    => true,
531
+                ),
532
+                'net_sales' => array(
533
+                    'description' => __( 'Net sales in the period.', 'invoicing' ),
534
+                    'type'        => 'string',
535
+                    'context'     => array( 'view' ),
536
+                    'readonly'    => true,
537
+                ),
538
+                'average_sales' => array(
539
+                    'description' => __( 'Average net daily sales.', 'invoicing' ),
540
+                    'type'        => 'string',
541
+                    'context'     => array( 'view' ),
542
+                    'readonly'    => true,
543
+                ),
544
+                'average_total_sales' => array(
545
+                    'description' => __( 'Average gross daily sales.', 'invoicing' ),
546
+                    'type'        => 'string',
547
+                    'context'     => array( 'view' ),
548
+                    'readonly'    => true,
549
+                ),
550
+                'total_invoices'  => array(
551
+                    'description' => __( 'Number of paid invoices.', 'invoicing' ),
552
+                    'type'        => 'integer',
553
+                    'context'     => array( 'view' ),
554
+                    'readonly'    => true,
555
+                ),
556
+                'total_items' => array(
557
+                    'description' => __( 'Number of items purchased.', 'invoicing' ),
558
+                    'type'        => 'integer',
559
+                    'context'     => array( 'view' ),
560
+                    'readonly'    => true,
561
+                ),
562
+                'refunded_items' => array(
563
+                    'description' => __( 'Number of items refunded.', 'invoicing' ),
564
+                    'type'        => 'integer',
565
+                    'context'     => array( 'view' ),
566
+                    'readonly'    => true,
567
+                ),
568
+                'total_tax' => array(
569
+                    'description' => __( 'Total charged for taxes.', 'invoicing' ),
570
+                    'type'        => 'string',
571
+                    'context'     => array( 'view' ),
572
+                    'readonly'    => true,
573
+                ),
574
+                'total_refunded_tax' => array(
575
+                    'description' => __( 'Total refunded for taxes.', 'invoicing' ),
576
+                    'type'        => 'string',
577
+                    'context'     => array( 'view' ),
578
+                    'readonly'    => true,
579
+                ),
580
+                'total_fees' => array(
581
+                    'description' => __( 'Total fees charged.', 'invoicing' ),
582
+                    'type'        => 'string',
583
+                    'context'     => array( 'view' ),
584
+                    'readonly'    => true,
585
+                ),
586
+                'total_refunds' => array(
587
+                    'description' => __( 'Total of refunded invoices.', 'invoicing' ),
588
+                    'type'        => 'integer',
589
+                    'context'     => array( 'view' ),
590
+                    'readonly'    => true,
591
+                ),
592
+                'net_refunds' => array(
593
+                    'description' => __( 'Net of refunded invoices.', 'invoicing' ),
594
+                    'type'        => 'integer',
595
+                    'context'     => array( 'view' ),
596
+                    'readonly'    => true,
597
+                ),
598
+                'total_discount' => array(
599
+                    'description' => __( 'Total of discounts used.', 'invoicing' ),
600
+                    'type'        => 'integer',
601
+                    'context'     => array( 'view' ),
602
+                    'readonly'    => true,
603
+                ),
604
+                'totals' => array(
605
+                    'description' => __( 'Totals.', 'invoicing' ),
606
+                    'type'        => 'array',
607
+                    'items'       => array(
608
+                        'type'    => 'array',
609
+                    ),
610
+                    'context'     => array( 'view' ),
611
+                    'readonly'    => true,
612
+                ),
613
+                'interval' => array(
614
+                    'description' => __( 'Number of months/days in the report period.', 'invoicing' ),
615
+                    'type'        => 'integer',
616
+                    'context'     => array( 'view' ),
617
+                    'readonly'    => true,
618
+                ),
619
+                'grouped_by' => array(
620
+                    'description' => __( 'The period used to group the totals.', 'invoicing' ),
621
+                    'type'        => 'string',
622
+                    'context'     => array( 'view' ),
623
+                    'enum'        => array( 'day', 'month' ),
624
+                    'readonly'    => true,
625
+                ),
626
+                'currency' => array(
627
+                    'description' => __( 'The default store currency.', 'invoicing' ),
628
+                    'type'        => 'string',
629
+                    'context'     => array( 'view' ),
630
+                    'readonly'    => true,
631
+                ),
632
+                'currency_symbol' => array(
633
+                    'description' => __( 'The default store currency symbol.', 'invoicing' ),
634
+                    'type'        => 'string',
635
+                    'context'     => array( 'view' ),
636
+                    'readonly'    => true,
637
+                ),
638
+                'currency_position' => array(
639
+                    'description' => __( 'The default store currency position.', 'invoicing' ),
640
+                    'type'        => 'string',
641
+                    'context'     => array( 'view' ),
642
+                    'readonly'    => true,
643
+                ),
644
+                'decimal_places' => array(
645
+                    'description' => __( 'The default store decimal places.', 'invoicing' ),
646
+                    'type'        => 'string',
647
+                    'context'     => array( 'view' ),
648
+                    'readonly'    => true,
649
+                ),
650
+                'thousands_sep' => array(
651
+                    'description' => __( 'The default store thousands separator.', 'invoicing' ),
652
+                    'type'        => 'string',
653
+                    'context'     => array( 'view' ),
654
+                    'readonly'    => true,
655
+                ),
656
+                'decimals_sep' => array(
657
+                    'description' => __( 'The default store decimals separator.', 'invoicing' ),
658
+                    'type'        => 'string',
659
+                    'context'     => array( 'view' ),
660
+                    'readonly'    => true,
661
+                ),
662
+            ),
663
+        );
664
+
665
+        return $this->add_additional_fields_schema( $schema );
666
+
667
+    }
668 668
 
669 669
 }
Please login to merge, or discard this patch.
includes/api/class-getpaid-rest-report-top-sellers-controller.php 1 patch
Indentation   +175 added lines, -175 removed lines patch added patch discarded remove patch
@@ -18,179 +18,179 @@
 block discarded – undo
18 18
  */
19 19
 class GetPaid_REST_Report_Top_Sellers_Controller extends GetPaid_REST_Report_Sales_Controller {
20 20
 
21
-	/**
22
-	 * Route base.
23
-	 *
24
-	 * @var string
25
-	 */
26
-	protected $rest_base = 'reports/top_sellers';
27
-
28
-	/**
29
-	 * Get top sellers report.
30
-	 *
31
-	 * @param WP_REST_Request $request
32
-	 * @return array|WP_Error
33
-	 */
34
-	public function get_items( $request ) {
35
-
36
-		// Prepare items.
37
-		$this->report_range = $this->get_date_range( $request );
38
-		$report_data        = $this->get_report_data();
39
-
40
-		$top_sellers = array();
41
-
42
-		foreach ( $report_data as $item ) {
43
-
44
-			$item_obj  = new WPInv_Item( $item );
45
-			$item_name = $item->invoice_item_name;
46
-			$item_qty  = absint( $item->invoice_item_qty );
47
-			$item_id   = absint( $item->invoice_item_id );
48
-			$price     = sanitize_text_field( wpinv_price( $item->invoice_item_price ) );
49
-
50
-			$item_obj  = new WPInv_Item( $item_id );
51
-
52
-			if ( $item_obj->exists() ) {
53
-				$item_name = $item_obj->get_name();
54
-			} else {
55
-				$item_id   = 0; 
56
-			}
57
-
58
-			$top_sellers[] = array(
59
-				'name'               =>sanitize_text_field( $item_name ),
60
-				'item_id'            => $item_id,
61
-				'quantity'           => $item_qty,
62
-				'earnings'           => wpinv_round_amount( $item->invoice_item_price ),
63
-				'earnings_formatted' => sanitize_text_field( wpinv_price( $price ) ),
64
-			);
65
-
66
-		}
67
-
68
-		$data = array();
69
-		foreach ( $top_sellers as $top_seller ) {
70
-			$item   = $this->prepare_item_for_response( (object) $top_seller, $request );
71
-			$data[] = $this->prepare_response_for_collection( $item );
72
-		}
73
-
74
-		return rest_ensure_response( $data );
75
-
76
-	}
77
-
78
-	/**
79
-	 * Prepare a report sales object for serialization.
80
-	 *
81
-	 * @param stdClass $top_seller
82
-	 * @param WP_REST_Request $request Request object.
83
-	 * @return WP_REST_Response $response Response data.
84
-	 */
85
-	public function prepare_item_for_response( $top_seller, $request ) {
86
-		$data    = (array) $top_seller;
87
-
88
-		$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
89
-		$data    = $this->add_additional_fields_to_object( $data, $request );
90
-		$data    = $this->filter_response_by_context( $data, $context );
91
-
92
-		// Wrap the data in a response object.
93
-		$response = rest_ensure_response( $data );
94
-		$links = array(
95
-			'about' => array(
96
-				'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
97
-			),
98
-		);
99
-
100
-		if ( ! empty( $top_seller->item_id ) ) {
101
-			$links['item']   = array(
102
-				'href'       => rest_url( sprintf( '/%s/items/%s', $this->namespace, $top_seller->item_id ) ),
103
-				'embeddable' => true,
104
-			);
105
-		}
106
-
107
-		$response->add_links( $links );
108
-		return apply_filters( 'getpaid_rest_prepare_report_top_sellers', $response, $top_seller, $request );
109
-	}
110
-
111
-	/**
112
-	 * Get all data needed for this report and store in the class.
113
-	 */
114
-	protected function query_report_data() {
115
-
116
-		$this->report_data = GetPaid_Reports_Helper::get_invoice_report_data(
117
-			array(
118
-				'data'              => array(
119
-					'quantity'      => array(
120
-						'type'            => 'invoice_item',
121
-						'function'        => 'SUM',
122
-						'name'            => 'invoice_item_qty',
123
-					),
124
-					'item_id'             => array(
125
-						'type'            => 'invoice_item',
126
-						'function'        => '',
127
-						'name'            => 'invoice_item_id',
128
-					),
129
-					'item_name'           => array(
130
-						'type'            => 'invoice_item',
131
-						'function'        => '',
132
-						'name'            => 'invoice_item_name',
133
-					),
134
-					'price'               => array(
135
-						'type'            => 'invoice_item',
136
-						'function'        => 'SUM',
137
-						'name'            => 'invoice_item_price',
138
-					),
139
-				),
140
-				'group_by'       => 'invoice_item_id',
141
-				'order_by'       => 'invoice_item_qty DESC',
142
-				'query_type'     => 'get_results',
143
-				'limit'          => 10,
144
-				'filter_range'   => $this->report_range,
145
-			)
146
-		);
147
-
148
-	}
149
-
150
-	/**
151
-	 * Get the Report's schema, conforming to JSON Schema.
152
-	 *
153
-	 * @return array
154
-	 */
155
-	public function get_item_schema() {
156
-		$schema = array(
157
-			'$schema'    => 'http://json-schema.org/draft-04/schema#',
158
-			'title'      => 'top_sellers_report',
159
-			'type'       => 'object',
160
-			'properties' => array(
161
-				'name' => array(
162
-					'description' => __( 'Item name.', 'invoicing' ),
163
-					'type'        => 'string',
164
-					'context'     => array( 'view' ),
165
-					'readonly'    => true,
166
-				),
167
-				'item_id'         => array(
168
-					'description' => __( 'Item ID.', 'invoicing' ),
169
-					'type'        => 'integer',
170
-					'context'     => array( 'view' ),
171
-					'readonly'    => true,
172
-				),
173
-				'quantity' => array(
174
-					'description' => __( 'Total number of purchases.', 'invoicing' ),
175
-					'type'        => 'integer',
176
-					'context'     => array( 'view' ),
177
-					'readonly'    => true,
178
-				),
179
-				'earnings' => array(
180
-					'description' => __( 'Total earnings for the item.', 'invoicing' ),
181
-					'type'        => 'double',
182
-					'context'     => array( 'view' ),
183
-					'readonly'    => true,
184
-				),
185
-				'earnings_formatted"' => array(
186
-					'description' => __( 'Total earnings (formatted) for the item.', 'invoicing' ),
187
-					'type'        => 'string',
188
-					'context'     => array( 'view' ),
189
-					'readonly'    => true,
190
-				),
191
-			),
192
-		);
193
-
194
-		return $this->add_additional_fields_schema( $schema );
195
-	}
21
+    /**
22
+     * Route base.
23
+     *
24
+     * @var string
25
+     */
26
+    protected $rest_base = 'reports/top_sellers';
27
+
28
+    /**
29
+     * Get top sellers report.
30
+     *
31
+     * @param WP_REST_Request $request
32
+     * @return array|WP_Error
33
+     */
34
+    public function get_items( $request ) {
35
+
36
+        // Prepare items.
37
+        $this->report_range = $this->get_date_range( $request );
38
+        $report_data        = $this->get_report_data();
39
+
40
+        $top_sellers = array();
41
+
42
+        foreach ( $report_data as $item ) {
43
+
44
+            $item_obj  = new WPInv_Item( $item );
45
+            $item_name = $item->invoice_item_name;
46
+            $item_qty  = absint( $item->invoice_item_qty );
47
+            $item_id   = absint( $item->invoice_item_id );
48
+            $price     = sanitize_text_field( wpinv_price( $item->invoice_item_price ) );
49
+
50
+            $item_obj  = new WPInv_Item( $item_id );
51
+
52
+            if ( $item_obj->exists() ) {
53
+                $item_name = $item_obj->get_name();
54
+            } else {
55
+                $item_id   = 0; 
56
+            }
57
+
58
+            $top_sellers[] = array(
59
+                'name'               =>sanitize_text_field( $item_name ),
60
+                'item_id'            => $item_id,
61
+                'quantity'           => $item_qty,
62
+                'earnings'           => wpinv_round_amount( $item->invoice_item_price ),
63
+                'earnings_formatted' => sanitize_text_field( wpinv_price( $price ) ),
64
+            );
65
+
66
+        }
67
+
68
+        $data = array();
69
+        foreach ( $top_sellers as $top_seller ) {
70
+            $item   = $this->prepare_item_for_response( (object) $top_seller, $request );
71
+            $data[] = $this->prepare_response_for_collection( $item );
72
+        }
73
+
74
+        return rest_ensure_response( $data );
75
+
76
+    }
77
+
78
+    /**
79
+     * Prepare a report sales object for serialization.
80
+     *
81
+     * @param stdClass $top_seller
82
+     * @param WP_REST_Request $request Request object.
83
+     * @return WP_REST_Response $response Response data.
84
+     */
85
+    public function prepare_item_for_response( $top_seller, $request ) {
86
+        $data    = (array) $top_seller;
87
+
88
+        $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
89
+        $data    = $this->add_additional_fields_to_object( $data, $request );
90
+        $data    = $this->filter_response_by_context( $data, $context );
91
+
92
+        // Wrap the data in a response object.
93
+        $response = rest_ensure_response( $data );
94
+        $links = array(
95
+            'about' => array(
96
+                'href' => rest_url( sprintf( '%s/reports', $this->namespace ) ),
97
+            ),
98
+        );
99
+
100
+        if ( ! empty( $top_seller->item_id ) ) {
101
+            $links['item']   = array(
102
+                'href'       => rest_url( sprintf( '/%s/items/%s', $this->namespace, $top_seller->item_id ) ),
103
+                'embeddable' => true,
104
+            );
105
+        }
106
+
107
+        $response->add_links( $links );
108
+        return apply_filters( 'getpaid_rest_prepare_report_top_sellers', $response, $top_seller, $request );
109
+    }
110
+
111
+    /**
112
+     * Get all data needed for this report and store in the class.
113
+     */
114
+    protected function query_report_data() {
115
+
116
+        $this->report_data = GetPaid_Reports_Helper::get_invoice_report_data(
117
+            array(
118
+                'data'              => array(
119
+                    'quantity'      => array(
120
+                        'type'            => 'invoice_item',
121
+                        'function'        => 'SUM',
122
+                        'name'            => 'invoice_item_qty',
123
+                    ),
124
+                    'item_id'             => array(
125
+                        'type'            => 'invoice_item',
126
+                        'function'        => '',
127
+                        'name'            => 'invoice_item_id',
128
+                    ),
129
+                    'item_name'           => array(
130
+                        'type'            => 'invoice_item',
131
+                        'function'        => '',
132
+                        'name'            => 'invoice_item_name',
133
+                    ),
134
+                    'price'               => array(
135
+                        'type'            => 'invoice_item',
136
+                        'function'        => 'SUM',
137
+                        'name'            => 'invoice_item_price',
138
+                    ),
139
+                ),
140
+                'group_by'       => 'invoice_item_id',
141
+                'order_by'       => 'invoice_item_qty DESC',
142
+                'query_type'     => 'get_results',
143
+                'limit'          => 10,
144
+                'filter_range'   => $this->report_range,
145
+            )
146
+        );
147
+
148
+    }
149
+
150
+    /**
151
+     * Get the Report's schema, conforming to JSON Schema.
152
+     *
153
+     * @return array
154
+     */
155
+    public function get_item_schema() {
156
+        $schema = array(
157
+            '$schema'    => 'http://json-schema.org/draft-04/schema#',
158
+            'title'      => 'top_sellers_report',
159
+            'type'       => 'object',
160
+            'properties' => array(
161
+                'name' => array(
162
+                    'description' => __( 'Item name.', 'invoicing' ),
163
+                    'type'        => 'string',
164
+                    'context'     => array( 'view' ),
165
+                    'readonly'    => true,
166
+                ),
167
+                'item_id'         => array(
168
+                    'description' => __( 'Item ID.', 'invoicing' ),
169
+                    'type'        => 'integer',
170
+                    'context'     => array( 'view' ),
171
+                    'readonly'    => true,
172
+                ),
173
+                'quantity' => array(
174
+                    'description' => __( 'Total number of purchases.', 'invoicing' ),
175
+                    'type'        => 'integer',
176
+                    'context'     => array( 'view' ),
177
+                    'readonly'    => true,
178
+                ),
179
+                'earnings' => array(
180
+                    'description' => __( 'Total earnings for the item.', 'invoicing' ),
181
+                    'type'        => 'double',
182
+                    'context'     => array( 'view' ),
183
+                    'readonly'    => true,
184
+                ),
185
+                'earnings_formatted"' => array(
186
+                    'description' => __( 'Total earnings (formatted) for the item.', 'invoicing' ),
187
+                    'type'        => 'string',
188
+                    'context'     => array( 'view' ),
189
+                    'readonly'    => true,
190
+                ),
191
+            ),
192
+        );
193
+
194
+        return $this->add_additional_fields_schema( $schema );
195
+    }
196 196
 }
Please login to merge, or discard this patch.