Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for specifying filters when searching orders. #43356

Merged
merged 12 commits into from Jan 16, 2024
Merged

Conversation

vedanshujain
Copy link
Contributor

@vedanshujain vedanshujain commented Jan 8, 2024

Submission Review Guidelines:

Changes proposed in this Pull Request:

This PR adds a select box to the left of the search button to the admin HPOS screen. This allows merchants to select whether they want to search in products or in customer data for the term that they are searching. The primary reason here is performance, in testing on a store with 2.5 million orders, it would take around 1.3s ~ 1.5s to search in the product, about 2.38 ~ 3s to search in customers, but about 5 ~ 6s to search in both.

This PR enables merchants to decide where they want to search, and that way they can enjoy about 2x faster searching when they want to search for products or customers.

Additionally, this also refactors the OrderTableSearchQuery class to support more filters down the line.

Partially addresses #41454

How to test the changes in this Pull Request:

Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:

  1. On shop with HPOS authoritative, create a product called "Product Common".
  2. Create an order with this product. Make sure that you do not use the term "Customer" in any of the customer field (name, address, etc).
  3. Create another order without this product. Make sure that you do not use the term "Product" in any of the fields. In the customer name, add "Customer Common".
  4. Go admin view at /wp-admin/admin.php?page=wc-orders and see the search form in top right corner:
Screenshot 2024-01-09 at 2 39 54 PM 5. Search for term "Product" while having "Customers" selected in the dropdown. No orders should show up.
  1. Search for term "Customer" while having "Customers" selected in the dropdown. Order created in step 3 should show up.
  2. Search for term "Common" while having "Customers" selected in the dropdown. Order created in step 3 should show up, but order created in step 2 will not.
  3. Similarly, repeat the same for terms "Product", "Customer" and "Common" with "Product" selected in dropdown. No orders will show for term "Customer", whereas, order created in step 2 should show up for term "Product" and "Common".
  4. Repeat the same for terms "Product", "Customer" and "Common" with "All" selected in dropdown. The behavior here should be exactly the same as the trunk, i.e. order in step 2 will show up for Product, order in step 3 will show for Customer, and both the orders will show up for "Common".

Changelog entry

  • Automatically create a changelog entry from the details below.

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement

Message

Allow selecting search criteria - Products/Customers/All when searching orders.

Comment

@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Jan 8, 2024
@vedanshujain vedanshujain changed the title Add support for specifying filters when searching onders. Add support for specifying filters when searching orders. Jan 8, 2024
@vedanshujain vedanshujain marked this pull request as ready for review January 9, 2024 09:15
@vedanshujain vedanshujain reopened this Jan 9, 2024
Copy link
Contributor

github-actions bot commented Jan 9, 2024

Test Results Summary

Commit SHA: 55bf3c8

Test 🧪Passed ✅Failed 🚨Broken 🚧Skipped ⏭️Unknown ❔Total 📊Duration ⏱️
API Tests25900202610m 37s
E2E Tests266001702835m 50s

To view the full API test report, click here.
To view the full E2E test report, click here.
To view all test reports, visit the WooCommerce Test Reports Dashboard.

@vedanshujain vedanshujain requested review from a team and lsinger and removed request for a team January 9, 2024 09:52
Copy link
Contributor

github-actions bot commented Jan 9, 2024

Hi @lsinger,

Apart from reviewing the code changes, please make sure to review the testing instructions as well.

You can follow this guide to find out what good testing instructions should look like:
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions

1 similar comment
Copy link
Contributor

github-actions bot commented Jan 9, 2024

Hi @lsinger,

Apart from reviewing the code changes, please make sure to review the testing instructions as well.

You can follow this guide to find out what good testing instructions should look like:
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions

Copy link
Contributor

@lsinger lsinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests well and almost as described. I believe that the differences between the testing instructions and my testing are to be expected, however?

Similarly, repeat the same for terms "Product", "Customer" and "Common" with "Product" selected in dropdown. No orders will show for term "Customer", whereas, order created in step 2 should show up for term "Product" and "Common".

When searching for "Common" or "Product", both orders show up, as they both contain the "Product Common" product. I assume this is the correct behavior.

Repeat the same for terms "Product", "Customer" and "Common" with "All" selected in dropdown. The behavior here should be exactly the same as the trunk, i.e. order in step 2 will show up for Product, order in step 3 will show for Customer, and both the orders will show up for "Common".

Same issue: when searching for "Common" or "Product", both orders show up, as they both contain the "Product Common" product. Again I assume this is the correct behavior.

When searching for a valid STREET CITY no results are returned, whereas searching for STREET or CITY does return the correct results. In the future we could maybe OR the terms from the search box and then also support adding quotes to ensure only full strings are matched. (I'd consider this definitely out of scope for this PR, FWIW.) I was reminded of this when searching for FIRSTNAME LASTNAME, which does work.

I left a few nitpicks that I'd all consider optional. If the differences between the testing instructions and my testing mentioned above look correct to you as well then I believe this is good to go.

}

/**
* Generate JOIN clause for different search filter.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Generate JOIN clause for different search filter.
* Generate JOIN clause for a given search filter.


/**
* Generate JOIN clause for different search filter.
* Right now we only have the products filter that actually does any join, but in future we may add more, for example, in order search, or payment tokens etc. This function is to make it easier to add more filters in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Right now we only have the products filter that actually does any join, but in future we may add more, for example, in order search, or payment tokens etc. This function is to make it easier to add more filters in the future.
* Right now we only have the products filter that actually does a JOIN, but in the future we may add more -- for example, in order search, payment tokens, and so on. This function makes it easier to add more filters in the future.

* Generate JOIN clause for different search filter.
* Right now we only have the products filter that actually does any join, but in future we may add more, for example, in order search, or payment tokens etc. This function is to make it easier to add more filters in the future.
*
* If a search filter needs a join, it will also need a where clause.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* If a search filter needs a join, it will also need a where clause.
* If a search filter needs a JOIN, it will also need a WHERE clause.

'search_query_items.order_item_name LIKE %s',
'%' . $wpdb->esc_like( $this->search_term ) . '%'
) . " OR `$order_table`.id IN ( $meta_sub_query ) ";
$where = implode( ' OR ', $where );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this pattern where we assign a variable to itself and in doing so change its type (from array to string in this case). We could either introduce a different name for either the array or the string, or pull the implode into the return. What do you think? (Optional nitpick.)


return " ( $where ) ";
}

/**
* Generates where clause for different search filter. Right now we only have the products and customers filter that actually use any `where`, but in future we may add more, for example, in order search, or payment tokens etc. This function is to make it easier to add more filters in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Generates where clause for different search filter. Right now we only have the products and customers filter that actually use any `where`, but in future we may add more, for example, in order search, or payment tokens etc. This function is to make it easier to add more filters in the future.
* Generates WHERE clause for a given search filter. Right now we only have the products and customers filters that actually use WHERE, but in the future we may add more -- for example, in order search, payment tokens, and so on. This function makes it easier to add more filters in the future.

return '-1';
}

// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $meta_fields is already escaped before imploding, $meta_table is hardcoded.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for explaining the exception, that's a great practice. ☺️

@@ -446,4 +446,95 @@ public function test_query_s_argument() {
$this->assertCount( 0, $query->orders );
}

/**
* Setup some dummy orders, to help testing the search filter.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Setup some dummy orders, to help testing the search filter.
* Set up some dummy orders to help test the search filter.

(Yes, this is super nitpicky. 😅)

(Not suggesting to change the setup_ method name also because set_ as a prefix implies a setter to me.)

}

/**
* @testDox The 'search_filter' argument works with 'all' param is passed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @testDox The 'search_filter' argument works with 'all' param is passed.
* @testDox The 'search_filter' argument works with an 'all' param passed in.

}

/**
* @testDox The 'search_filter' argument works with 'product' param is passed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @testDox The 'search_filter' argument works with 'product' param is passed.
* @testDox The 'search_filter' argument works with a 'product' param passed in.

}

/**
* @testDox The 'search_filter' argument works with 'customer' param is passed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @testDox The 'search_filter' argument works with 'customer' param is passed.
* @testDox The 'search_filter' argument works with a 'customer' param passed in.

@vedanshujain
Copy link
Contributor Author

@lsinger Addressed comments in a4eecee, could use a quick look.

Also, you are right, in testing instructions, the order is not supposed to contain the product at all, updated the testing instructions to reflect this.

@lsinger lsinger self-requested a review January 12, 2024 09:18
Copy link
Contributor

@lsinger lsinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few more nitpicky grammar notes (sorry! 😬) but generally looks great. Thanks!

}

/**
* @testDox The 'search_filter' argument works with a 'customer' param is passed in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @testDox The 'search_filter' argument works with a 'customer' param is passed in.
* @testDox The 'search_filter' argument works with a 'customer' param passed in.

}

/**
* @testDox The 'search_filter' argument works with a 'product' param is passed in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @testDox The 'search_filter' argument works with a 'product' param is passed in.
* @testDox The 'search_filter' argument works with a 'product' param passed in.

}

/**
* @testDox The 'search_filter' argument works with an 'all' param is passed in.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @testDox The 'search_filter' argument works with an 'all' param is passed in.
* @testDox The 'search_filter' argument works with an 'all' param passed in.

}

/**
* Generates WHERE clause for a given search filter. Right now we only have the products and customers filters that actually use WHERE, but the in future we may add more -- for example, order custom fields, payment tokens etc. This function makes it easier to add more filters in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Generates WHERE clause for a given search filter. Right now we only have the products and customers filters that actually use WHERE, but the in future we may add more -- for example, order custom fields, payment tokens etc. This function makes it easier to add more filters in the future.
* Generates WHERE clause for a given search filter. Right now we only have the products and customers filters that actually use WHERE, but in the future we may add more -- for example, custom order fields, payment tokens, and so on. This function makes it easier to add more filters in the future.


/**
* Generate JOIN clause for a given search filter.
* Right now we only have the products filter that actually does a JOIN, but in the future we may add more -- for example, custom order fields, payment tokens and so on. This function makes it easier to add more filters in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Right now we only have the products filter that actually does a JOIN, but in the future we may add more -- for example, custom order fields, payment tokens and so on. This function makes it easier to add more filters in the future.
* Right now we only have the products filter that actually does a JOIN, but in the future we may add more -- for example, custom order fields, payment tokens, and so on. This function makes it easier to add more filters in the future.

@vedanshujain vedanshujain merged commit 4b401e5 into trunk Jan 16, 2024
33 of 34 checks passed
@vedanshujain vedanshujain deleted the fix/41454 branch January 16, 2024 15:07
@github-actions github-actions bot added this to the 8.6.0 milestone Jan 16, 2024
@github-actions github-actions bot added the needs: analysis Indicates if the PR requires a PR testing scrub session. label Jan 16, 2024
@vedanshujain
Copy link
Contributor Author

Note that all comments from last review were addressed in 55bf3c8

@nigeljamesstevenson nigeljamesstevenson added needs: external testing Indicates if the PR requires further testing conducted by testers external to the development team. status: analysis complete Indicates if a PR has been analysed by Solaris and removed needs: analysis Indicates if the PR requires a PR testing scrub session. labels Jan 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs: external testing Indicates if the PR requires further testing conducted by testers external to the development team. plugin: woocommerce Issues related to the WooCommerce Core plugin. status: analysis complete Indicates if a PR has been analysed by Solaris
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants