Added support for ordering by product name in products endpoint.

This commit is contained in:
Peter Fabian 2018-11-28 15:14:34 +01:00
parent 4b8969acc7
commit 8b80de9bc2
3 changed files with 138 additions and 2 deletions

View File

@ -221,6 +221,7 @@ class WC_Admin_REST_Reports_Products_Controller extends WC_REST_Reports_Controll
'gross_revenue',
'orders_count',
'items_sold',
'product_name',
),
'validate_callback' => 'rest_validate_request_arg',
);

View File

@ -62,6 +62,33 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
'permalink',
);
/**
* Fills ORDER BY clause of SQL request based on user supplied parameters.
*
* @param array $query_args Parameters supplied by the user.
* @return array
*/
protected function get_order_by_sql_params( $query_args ) {
global $wpdb;
$order_product_lookup_table = $wpdb->prefix . self::TABLE_NAME;
$sql_query['order_by_clause'] = '';
if ( isset( $query_args['orderby'] ) ) {
$sql_query['order_by_clause'] = $this->normalize_order_by( $query_args['orderby'] );
}
// Order by product name requires extra JOIN.
if ( false !== strpos( $sql_query['order_by_clause'], '_products' ) ) {
$sql_query['from_clause'] .= " JOIN {$wpdb->prefix}posts AS _products ON {$order_product_lookup_table}.product_id = _products.ID";
}
if ( isset( $query_args['order'] ) ) {
$sql_query['order_by_clause'] .= ' ' . $query_args['order'];
} else {
$sql_query['order_by_clause'] .= ' DESC';
}
return $sql_query;
}
/**
* Updates the database query with parameters used for Products report: categories and order status.
@ -87,8 +114,8 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
if ( is_array( $query_args['order_status'] ) && count( $query_args['order_status'] ) > 0 ) {
$statuses = array_map( array( $this, 'normalize_order_status' ), $query_args['order_status'] );
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}posts ON {$order_product_lookup_table}.order_id = {$wpdb->prefix}posts.ID";
$sql_query_params['where_clause'] .= " AND {$wpdb->prefix}posts.post_status IN ( '" . implode( "','", $statuses ) . "' ) ";
$sql_query_params['from_clause'] .= " JOIN {$wpdb->prefix}posts AS _orders ON {$order_product_lookup_table}.order_id = _orders.ID";
$sql_query_params['where_clause'] .= " AND _orders.post_status IN ( '" . implode( "','", $statuses ) . "' ) ";
}
return $sql_query_params;
@ -104,6 +131,9 @@ class WC_Admin_Reports_Products_Data_Store extends WC_Admin_Reports_Data_Store i
if ( 'date' === $order_by ) {
return 'date_created';
}
if ( 'product_name' === $order_by ) {
return '_products.post_title';
}
return $order_by;
}

View File

@ -62,4 +62,109 @@ class WC_Tests_Reports_Products extends WC_Unit_Test_Case {
$this->assertEquals( $expected_data, $query->get_data() );
}
public function test_order_by_product_name() {
WC_Helper_Reports::reset_stats_dbs();
// Populate all of the data.
$product = new WC_Product_Simple();
$product->set_name( 'A Test Product' );
$product->set_regular_price( 25 );
$product->save();
$product_2 = new WC_Product_Simple();
$product_2->set_name( 'B Test Product' );
$product_2->set_regular_price( 20 );
$product_2->save();
$date_created = time();
$date_created_2 = $date_created + 5;
$order = WC_Helper_Order::create_order( 1, $product );
$order->set_status( 'completed' );
$order->set_shipping_total( 10 );
$order->set_discount_total( 20 );
$order->set_discount_tax( 0 );
$order->set_cart_tax( 5 );
$order->set_shipping_tax( 2 );
$order->set_total( 97 ); // $25x4 products + $10 shipping - $20 discount + $7 tax.
$order->set_date_created( $date_created );
$order->save();
$order_2 = WC_Helper_Order::create_order( 1, $product_2 );
$order_2->set_status( 'completed' );
$order_2->set_shipping_total( 10 );
$order_2->set_discount_total( 20 );
$order_2->set_discount_tax( 0 );
$order_2->set_cart_tax( 5 );
$order_2->set_shipping_tax( 2 );
$order_2->set_total( 77 ); // $20x4 products + $10 shipping - $20 discount + $7 tax.
$order_2->set_date_created( $date_created_2 );
$order_2->save();
$data_store = new WC_Admin_Reports_Products_Data_Store();
$start_time = date( 'Y-m-d H:00:00', $order->get_date_created()->getOffsetTimestamp() );
$end_time = date( 'Y-m-d H:00:00', $order_2->get_date_created()->getOffsetTimestamp() + HOUR_IN_SECONDS );
// Test retrieving the stats through the data store, default order by date/time desc.
$args = array(
'after' => $start_time,
'before' => $end_time,
);
$data = $data_store->get_data( $args );
$expected_data = (object) array(
'total' => 2,
'pages' => 1,
'page_no' => 1,
'data' => array(
0 => array(
'product_id' => $product_2->get_id(),
'items_sold' => 4,
'gross_revenue' => 80.0, // $20 * 4.
'orders_count' => 1,
),
1 => array(
'product_id' => $product->get_id(),
'items_sold' => 4,
'gross_revenue' => 100.0, // $25 * 4.
'orders_count' => 1,
),
),
);
$this->assertEquals( $expected_data, $data );
// Test retrieving the stats through the data store, order by product name asc.
$args = array(
'after' => $start_time,
'before' => $end_time,
'order_by' => 'product_name',
'order' => 'asc',
);
$data = $data_store->get_data( $args );
$expected_data = (object) array(
'total' => 2,
'pages' => 1,
'page_no' => 1,
'data' => array(
0 => array(
'product_id' => $product->get_id(),
'items_sold' => 4,
'gross_revenue' => 100.0, // $25 * 4.
'orders_count' => 1,
),
1 => array(
'product_id' => $product_2->get_id(),
'items_sold' => 4,
'gross_revenue' => 80.0, // $20 * 4.
'orders_count' => 1,
),
),
);
$this->assertEquals( $expected_data, $data );
// Test retrieving the stats through the query class.
$query = new WC_Admin_Reports_Products_Query( $args );
$this->assertEquals( $expected_data, $query->get_data() );
}
}