PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/woocommerce/includes/cli/class-wc-cli-report.php

https://gitlab.com/webkod3r/tripolis
PHP | 372 lines | 179 code | 47 blank | 146 comment | 24 complexity | 58b0af0368b6d50237486e828762e457 MD5 | raw file
  1. <?php
  2. /**
  3. * Show Reports.
  4. *
  5. * @since 2.5.0
  6. * @package WooCommerce/CLI
  7. * @category CLI
  8. * @author WooThemes
  9. */
  10. class WC_CLI_Report extends WC_CLI_Command {
  11. /**
  12. * List reports.
  13. *
  14. * ## OPTIONS
  15. *
  16. * [--format=<format>]
  17. * : Acceptec values: table, csv, json, count, ids. Default: table.
  18. *
  19. * ## EXAMPLES
  20. *
  21. * wp wc report list
  22. *
  23. * @subcommand list
  24. * @since 2.5.0
  25. */
  26. public function list_( $__, $assoc_args ) {
  27. $reports = array( 'sales', 'sales/top_sellers' );
  28. $formatter = $this->get_formatter(
  29. array_merge(
  30. array( 'fields' => array_keys( $reports ) ),
  31. $assoc_args
  32. )
  33. );
  34. if ( 'ids' === $formatter->format ) {
  35. echo implode( ' ', $reports );
  36. } else {
  37. $formatter->display_item( $reports );
  38. }
  39. }
  40. /**
  41. * View sales report.
  42. *
  43. * ## OPTIONS
  44. *
  45. * [--field=<field>]
  46. * : Instead of returning the whole report fields, returns the value of a single fields.
  47. *
  48. * [--fields=<fields>]
  49. * : Get a specific subset of the report's fields.
  50. *
  51. * [--format=<format>]
  52. * : Accepted values: table, json, csv. Default: table.
  53. *
  54. * [--period=<period>]
  55. * : The supported periods are: week, month, last_month, and year. If invalid
  56. * period is supplied, week is used. If period is not specified, the current
  57. * day is used.
  58. *
  59. * [--date_min]
  60. * : Return sales for a specific start date. The date need to be in the YYYY-MM-AA format.
  61. *
  62. * [--date_max]
  63. * : Return sales for a specific end date. The dates need to be in the YYYY-MM-AA format.
  64. *
  65. * [--limit]
  66. * : Limit report result. Default: 12.
  67. *
  68. * ## AVAILABLE FIELDS
  69. *
  70. * These fields are available for get command:
  71. *
  72. * * total_sales
  73. * * average_sales
  74. * * total_orders
  75. * * total_items
  76. * * total_tax
  77. * * total_shipping
  78. * * total_discount
  79. * * totals_grouped_by
  80. * * totals
  81. * * total_customers
  82. *
  83. * ## EXAMPLES
  84. *
  85. * wp wc report sales
  86. *
  87. * wp wc report sales --period=last_month
  88. *
  89. * @since 2.5.0
  90. */
  91. public function sales( $__, $assoc_args ) {
  92. $reporter = $this->get_reporter( $assoc_args );
  93. // new customers
  94. $users_query = new WP_User_Query(
  95. array(
  96. 'fields' => array( 'user_registered' ),
  97. 'role' => 'customer',
  98. )
  99. );
  100. $customers = $users_query->get_results();
  101. foreach ( $customers as $key => $customer ) {
  102. if ( strtotime( $customer->user_registered ) < $reporter->start_date || strtotime( $customer->user_registered ) > $reporter->end_date ) {
  103. unset( $customers[ $key ] );
  104. }
  105. }
  106. $total_customers = count( $customers );
  107. $report_data = $reporter->get_report_data();
  108. $period_totals = array();
  109. // setup period totals by ensuring each period in the interval has data
  110. for ( $i = 0; $i <= $reporter->chart_interval; $i ++ ) {
  111. switch ( $reporter->chart_groupby ) {
  112. case 'day' :
  113. $time = date( 'Y-m-d', strtotime( "+{$i} DAY", $reporter->start_date ) );
  114. break;
  115. default :
  116. $time = date( 'Y-m', strtotime( "+{$i} MONTH", $reporter->start_date ) );
  117. break;
  118. }
  119. // set the customer signups for each period
  120. $customer_count = 0;
  121. foreach ( $customers as $customer ) {
  122. if ( date( ( 'day' == $reporter->chart_groupby ) ? 'Y-m-d' : 'Y-m', strtotime( $customer->user_registered ) ) == $time ) {
  123. $customer_count++;
  124. }
  125. }
  126. $period_totals[ $time ] = array(
  127. 'sales' => wc_format_decimal( 0.00, 2 ),
  128. 'orders' => 0,
  129. 'items' => 0,
  130. 'tax' => wc_format_decimal( 0.00, 2 ),
  131. 'shipping' => wc_format_decimal( 0.00, 2 ),
  132. 'discount' => wc_format_decimal( 0.00, 2 ),
  133. 'customers' => $customer_count,
  134. );
  135. }
  136. // add total sales, total order count, total tax and total shipping for each period
  137. foreach ( $report_data->orders as $order ) {
  138. $time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $order->post_date ) ) : date( 'Y-m', strtotime( $order->post_date ) );
  139. if ( ! isset( $period_totals[ $time ] ) ) {
  140. continue;
  141. }
  142. $period_totals[ $time ]['sales'] = wc_format_decimal( $order->total_sales, 2 );
  143. $period_totals[ $time ]['tax'] = wc_format_decimal( $order->total_tax + $order->total_shipping_tax, 2 );
  144. $period_totals[ $time ]['shipping'] = wc_format_decimal( $order->total_shipping, 2 );
  145. }
  146. foreach ( $report_data->order_counts as $order ) {
  147. $time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $order->post_date ) ) : date( 'Y-m', strtotime( $order->post_date ) );
  148. if ( ! isset( $period_totals[ $time ] ) ) {
  149. continue;
  150. }
  151. $period_totals[ $time ]['orders'] = (int) $order->count;
  152. }
  153. // add total order items for each period
  154. foreach ( $report_data->order_items as $order_item ) {
  155. $time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $order_item->post_date ) ) : date( 'Y-m', strtotime( $order_item->post_date ) );
  156. if ( ! isset( $period_totals[ $time ] ) ) {
  157. continue;
  158. }
  159. $period_totals[ $time ]['items'] = (int) $order_item->order_item_count;
  160. }
  161. // add total discount for each period
  162. foreach ( $report_data->coupons as $discount ) {
  163. $time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $discount->post_date ) ) : date( 'Y-m', strtotime( $discount->post_date ) );
  164. if ( ! isset( $period_totals[ $time ] ) ) {
  165. continue;
  166. }
  167. $period_totals[ $time ]['discount'] = wc_format_decimal( $discount->discount_amount, 2 );
  168. }
  169. $sales_data = array(
  170. 'total_sales' => $report_data->total_sales,
  171. 'net_sales' => $report_data->net_sales,
  172. 'average_sales' => $report_data->average_sales,
  173. 'total_orders' => $report_data->total_orders,
  174. 'total_items' => $report_data->total_items,
  175. 'total_tax' => wc_format_decimal( $report_data->total_tax + $report_data->total_shipping_tax, 2 ),
  176. 'total_shipping' => $report_data->total_shipping,
  177. 'total_refunds' => $report_data->total_refunds,
  178. 'total_discount' => $report_data->total_coupons,
  179. 'totals_grouped_by' => $reporter->chart_groupby,
  180. 'totals' => $period_totals,
  181. 'total_customers' => $total_customers,
  182. );
  183. $sales_data = apply_filters( 'woocommerce_cli_sales_report', $sales_data );
  184. if ( empty( $assoc_args['fields'] ) ) {
  185. $assoc_args['fields'] = array_keys( $sales_data );
  186. }
  187. $formatter = $this->get_formatter( $assoc_args );
  188. $formatter->display_item( $sales_data );
  189. }
  190. /**
  191. * View report of top sellers.
  192. *
  193. * ## OPTIONS
  194. *
  195. * [--<field>=<value>]
  196. * : Filter report based on report property.
  197. *
  198. * [--field=<field>]
  199. * : Prints the value of a single field for each seller.
  200. *
  201. * [--fields=<fields>]
  202. * : Limit the output to specific report fields.
  203. *
  204. * [--format=<format>]
  205. * : Acceptec values: table, csv, json, count, ids. Default: table.
  206. *
  207. * [--period=<period>]
  208. * : The supported periods are: week, month, last_month, and year. If invalid
  209. * period is supplied, week is used. If period is not specified, the current
  210. * day is used.
  211. *
  212. * [--date_min]
  213. * : Return sales for a specific start date. The date need to be in the YYYY-MM-AA format.
  214. *
  215. * [--date_max]
  216. * : Return sales for a specific end date. The dates need to be in the YYYY-MM-AA format.
  217. *
  218. * [--limit]
  219. * : Limit report result. Default: 12.
  220. *
  221. * ## AVAILABLE FIELDS
  222. *
  223. * These fields will be displayed by default for each row:
  224. *
  225. * * title
  226. * * product_id
  227. * * quantity
  228. *
  229. * ## EXAMPLES
  230. *
  231. * wp wc report top_sellers
  232. *
  233. * wp wc report top_sellers --period=last_month
  234. *
  235. * @since 2.5.0
  236. */
  237. public function top_sellers( $__, $assoc_args ) {
  238. $reporter = $this->get_reporter( $assoc_args );
  239. $top_sellers = $reporter->get_order_report_data( array(
  240. 'data' => array(
  241. '_product_id' => array(
  242. 'type' => 'order_item_meta',
  243. 'order_item_type' => 'line_item',
  244. 'function' => '',
  245. 'name' => 'product_id'
  246. ),
  247. '_qty' => array(
  248. 'type' => 'order_item_meta',
  249. 'order_item_type' => 'line_item',
  250. 'function' => 'SUM',
  251. 'name' => 'order_item_qty'
  252. )
  253. ),
  254. 'order_by' => 'order_item_qty DESC',
  255. 'group_by' => 'product_id',
  256. 'limit' => isset( $assoc_args['limit'] ) ? absint( $assoc_args['limit'] ) : 12,
  257. 'query_type' => 'get_results',
  258. 'filter_range' => true,
  259. ) );
  260. $top_sellers_data = array();
  261. foreach ( $top_sellers as $top_seller ) {
  262. $product = wc_get_product( $top_seller->product_id );
  263. if ( $product ) {
  264. $top_sellers_data[] = array(
  265. 'title' => $product->get_title(),
  266. 'product_id' => $top_seller->product_id,
  267. 'quantity' => $top_seller->order_item_qty,
  268. );
  269. }
  270. }
  271. $top_sellers_data = apply_filters( 'woocommerce_cli_top_sellers_report', $top_sellers_data );
  272. $formatter = $this->get_formatter( $assoc_args );
  273. if ( 'ids' === $formatter->format ) {
  274. $query_args['fields'] = 'ids';
  275. echo implode( ' ', wp_list_pluck( $top_sellers_data, 'product_id' ) );
  276. } else {
  277. $formatter->display_items( $top_sellers_data );
  278. }
  279. }
  280. /**
  281. * Setup the report object and parse any date filtering
  282. *
  283. * @since 2.5.0
  284. * @param array $assoc_args Arguments provided in when invoking the command
  285. * @return WC_Report_Sales_By_Date
  286. */
  287. private function get_reporter( $assoc_args ) {
  288. include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
  289. include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-date.php' );
  290. $report = new WC_Report_Sales_By_Date();
  291. if ( empty( $assoc_args['period'] ) ) {
  292. // custom date range
  293. $assoc_args['period'] = 'custom';
  294. if ( ! empty( $assoc_args['date_min'] ) || ! empty( $assoc_args['date_max'] ) ) {
  295. // overwrite _GET to make use of WC_Admin_Report::calculate_current_range() for custom date ranges
  296. $_GET['start_date'] = $this->parse_datetime( $assoc_args['date_min'] );
  297. $_GET['end_date'] = isset( $assoc_args['date_max'] ) ? $this->parse_datetime( $assoc_args['date_max'] ) : null;
  298. } else {
  299. // default custom range to today
  300. $_GET['start_date'] = $_GET['end_date'] = date( 'Y-m-d', current_time( 'timestamp' ) );
  301. }
  302. } else {
  303. // ensure period is valid
  304. if ( ! in_array( $assoc_args['period'], array( 'week', 'month', 'last_month', 'year' ) ) ) {
  305. $assoc_args['period'] = 'week';
  306. }
  307. // TODO: change WC_Admin_Report class to use "week" instead, as it's more consistent with other periods
  308. // allow "week" for period instead of "7day"
  309. if ( 'week' === $assoc_args['period'] ) {
  310. $assoc_args['period'] = '7day';
  311. }
  312. }
  313. $report->calculate_current_range( $assoc_args['period'] );
  314. return $report;
  315. }
  316. /**
  317. * Get default format fields that will be used in `list` and `get` subcommands.
  318. *
  319. * @since 2.5.0
  320. * @return string
  321. */
  322. protected function get_default_format_fields() {
  323. return 'title,product_id,quantity';
  324. }
  325. }