Fix updating WC customer without wordpress user (if multiple orders are present) (https://github.com/woocommerce/woocommerce-admin/pull/5825)

* Create get last order function that does not rely on Wordpress user, and add test for use case

* Add change log

* Make sure tests use the right index for comparison

* Order by date_created_gmt first and order id second, and wrote test for get_last_order

* Fix test assertion, and remove unnecessary parameter
This commit is contained in:
louwie17 2020-12-10 09:42:17 -04:00 committed by GitHub
parent e44193cb1d
commit 484e945460
3 changed files with 135 additions and 7 deletions

View File

@ -78,6 +78,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
- Enhancement: Tasks extensibility in Home Screen. #5794
- Enhancement: Add page parameter to override default wc-admin page in Navigation API. #5821
- Fix: Invalidate product count if the last product was updated in the list. #5790
- Fix: Updating (non wordpress user) customer with order data
== Changelog ==

View File

@ -132,6 +132,7 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
* Only updates customer if it is the customers last order.
*
* @param int $post_id of order.
* @return true|-1
*/
public static function sync_order_customer( $post_id ) {
global $wpdb;
@ -142,11 +143,10 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
$order = wc_get_order( $post_id );
$customer_id = self::get_existing_customer_id_from_order( $order );
if ( ! $customer_id ) {
if ( false === $customer_id ) {
return -1;
}
$customer = new \WC_Customer( $customer_id );
$last_order = $customer->get_last_order();
$last_order = self::get_last_order( $customer_id );
if ( ! $last_order || $order->get_id() !== $last_order->get_id() ) {
return -1;
@ -626,6 +626,32 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
return $customer_id ? (int) $customer_id : false;
}
/**
* Retrieve the last order made by a customer.
*
* @param int $customer_id Customer ID.
* @return object WC_Order|false.
*/
public static function get_last_order( $customer_id ) {
global $wpdb;
$orders_table = $wpdb->prefix . 'wc_order_stats';
$last_order = $wpdb->get_var(
$wpdb->prepare(
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT order_id, date_created_gmt FROM {$orders_table}
WHERE customer_id = %d
ORDER BY date_created_gmt DESC, order_id DESC LIMIT 1",
// phpcs:enable
$customer_id
)
);
if ( ! $last_order ) {
return false;
}
return wc_get_order( absint( $last_order ) );
}
/**
* Retrieve the oldest orders made by a customer.
*

View File

@ -545,14 +545,115 @@ class WC_Tests_API_Reports_Customers extends WC_REST_Unit_Test_Case {
WC_Helper_Queue::run_all_pending();
// Didn't update anything.
$this->assertEquals( -1, $result );
$this->assertTrue( -1 === $result );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$response = $this->server->dispatch( $request );
$reports = $response->get_data();
$customer_index = array_search( 'admin@example.org', array_column( $reports, 'email' ), true );
$this->assertEquals( 200, $response->get_status() );
$this->assertNotEquals( 'Random', $reports[ $customer_index ]['city'] );
$this->assertNotEquals( 'FL', $reports[ $customer_index ]['state'] );
$this->assertNotEquals( '54321', $reports[ $customer_index ]['postcode'] );
}
/**
* Test sync order update with customer latest order info.
*/
public function test_sync_latest_order_customer_with_multiple_customers() {
wp_set_current_user( $this->user );
$order = WC_Helper_Order::create_order( 0 );
$order->set_status( 'completed' );
$order->set_total( 100 );
$order->save();
$order2 = WC_Helper_Order::create_order( 0 );
$order2->set_status( 'completed' );
$order2->set_total( 100 );
$order2->save();
$order3 = WC_Helper_Order::create_order( 0 );
$order3->set_status( 'completed' );
$order3->set_total( 100 );
$order3->set_billing_email( 'different@example.org' );
$order3->save();
WC_Helper_Queue::run_all_pending();
$customer_id = CustomersDataStore::get_existing_customer_id_from_order( $order );
$customer2_id = CustomersDataStore::get_existing_customer_id_from_order( $order2 );
$customer3_id = CustomersDataStore::get_existing_customer_id_from_order( $order3 );
$this->assertEquals( $customer_id, $customer2_id );
$this->assertNotEquals( $customer_id, $customer3_id );
// update order info.
$order3->set_billing_city( 'Random' );
$order3->set_billing_state( 'FL' );
$order3->set_billing_postcode( '54321' );
$order3->save();
WC_Helper_Queue::run_all_pending();
$result = CustomersDataStore::sync_order_customer( $order3->get_id() );
WC_Helper_Queue::run_all_pending();
// Didn't update anything.
$this->assertTrue( $result );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$response = $this->server->dispatch( $request );
$reports = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertFalse( 'Random' === $reports[0]['city'] );
$this->assertFalse( 'FL' === $reports[0]['state'] );
$this->assertFalse( '54321' === $reports[0]['postcode'] );
$first_customer_index = array_search( 'admin@example.org', array_column( $reports, 'email' ), true );
$second_customer_index = array_search( 'different@example.org', array_column( $reports, 'email' ), true );
// First customer.
$this->assertEquals( 'admin@example.org', $reports[ $first_customer_index ]['email'] );
$this->assertNotEquals( 'Random', $reports[ $first_customer_index ]['city'] );
$this->assertNotEquals( 'FL', $reports[ $first_customer_index ]['state'] );
$this->assertNotEquals( '54321', $reports[ $first_customer_index ]['postcode'] );
// Latest customer that should be updated.
$this->assertEquals( 'different@example.org', $reports[ $second_customer_index ]['email'] );
$this->assertEquals( 'Random', $reports[ $second_customer_index ]['city'] );
$this->assertEquals( 'FL', $reports[ $second_customer_index ]['state'] );
$this->assertEquals( '54321', $reports[ $second_customer_index ]['postcode'] );
}
/**
* Test get_last_order.
*/
public function test_get_last_order() {
wp_set_current_user( $this->user );
$order = WC_Helper_Order::create_order( 0 );
$order->set_status( 'completed' );
$order->set_total( 100 );
$order->save();
$order2 = WC_Helper_Order::create_order( 0 );
$order2->set_status( 'completed' );
$order2->set_total( 100 );
$order2->save();
$order3 = WC_Helper_Order::create_order( 0 );
$order3->set_status( 'completed' );
$order3->set_total( 100 );
$order3->save();
WC_Helper_Queue::run_all_pending();
$customer_id = CustomersDataStore::get_existing_customer_id_from_order( $order );
$customer2_id = CustomersDataStore::get_existing_customer_id_from_order( $order2 );
$customer3_id = CustomersDataStore::get_existing_customer_id_from_order( $order3 );
$this->assertEquals( $customer_id, $customer2_id );
$this->assertEquals( $customer_id, $customer3_id );
$latest_order = CustomersDataStore::get_last_order( $customer_id );
$this->assertEquals( $latest_order->get_id(), $order3->get_id() );
$order->set_date_created( time() + 60 );
$order->save();
WC_Helper_Queue::run_all_pending();
$latest_order = CustomersDataStore::get_last_order( $customer_id );
$this->assertEquals( $latest_order->get_id(), $order->get_id() );
}
}