OBPIH-6870 Add endpoint to fetch cycle count candidates#4981
OBPIH-6870 Add endpoint to fetch cycle count candidates#4981awalkowiak merged 3 commits intodevelopfrom
Conversation
| tags: product.tags?.collect { Tag tag -> | ||
| [ | ||
| id: tag.id, | ||
| tag: tag.tag, | ||
| ] | ||
| }, |
There was a problem hiding this comment.
I don't particularly appreciate placing any logic in the toJson function, I would rather move this part to a simple function and call it here, but it's only my opinion
| } | ||
| } | ||
|
|
||
| private static void getCandidatesSortOrder(String sort, String orderDirection, Criteria criteria, Set<String> usedAliases) { |
There was a problem hiding this comment.
I would name sort -> sortBy. Sort sounds like it should be desc or asc
There was a problem hiding this comment.
I'm fine with renaming it, but in my mind sort is what we sort by, and desc/asc is the direction.
| import org.pih.warehouse.product.Category | ||
| import org.pih.warehouse.product.ProductCatalog | ||
|
|
||
| class CycleCountCandidateFilterCommand extends PaginationCommand implements Validateable { |
There was a problem hiding this comment.
what about status? We want to be able to filter out candidates that already have a count in progress.
There was a problem hiding this comment.
It's not achievable yet, because the cycle count table doesn't exist. Moreover I think we still need to determine how we would want to join the status data to this query. In my mind we would have to modify the view to join the cycle count table to return status. I would not recommend doing an additional query to cycle count table and then filtering it out statically, because we might lose the pagination.
There was a problem hiding this comment.
We discussed this in the meeting, but I agree that we should modify the view to join Cycle Counts, and also Cycle Count Requests. We likely need both because Request is the table that holds productId and so that's how we'll join with Candidate. And then we'll fetch the Cycle Count associated with that request to get the Cycle Count status (for the purpose of filtering out rows)
But yes that's for a future ticket
| @Transactional | ||
| class CycleCountService { | ||
|
|
||
| List<CycleCountCandidate> getCandidates(CycleCountCandidateFilterCommand command, String facilityId) { |
There was a problem hiding this comment.
I skipped that part for now, because those fields were meant to be "included later". For now negative item count is hardcoded as null, and I am not sure what this actually will be later.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #4981 +/- ##
============================================
- Coverage 7.68% 7.67% -0.01%
- Complexity 828 834 +6
============================================
Files 601 605 +4
Lines 42340 42451 +111
Branches 10283 10308 +25
============================================
+ Hits 3252 3260 +8
- Misses 38614 38711 +97
- Partials 474 480 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| def getCandidates(CycleCountCandidateFilterCommand filterParams) { | ||
| List<CycleCountCandidate> candidates = cycleCountService.getCandidates(filterParams, params.facilityId) | ||
|
|
||
| render([data: candidates, totalCount: candidates.totalCount] as JSON) |
There was a problem hiding this comment.
is the "totalCount" what will be used to display the number next to the ALL PRODUCTS tab?
If so, I'm not sure this will work if we apply any filters since that will shrink the result set of the query (and presumably the totalCount) but we want the number to continue to show for the total number of un-filtered elements.
There was a problem hiding this comment.
totalCount is meant for the pagination, so as you mentioned, whenever any filters are applied, the totalCount changes as well. I haven't thought about the number next to the "ALL PRODUCTS", but if you say, this should not change regardless the filters, we could just set it on frontend once (during the initial fetch, when none filters would be applied), and not update it whenever we refetch the data.
| } | ||
|
|
||
|
|
||
| Map toJson() { |
There was a problem hiding this comment.
I'm surprised this is performant since we're fetching products, then their categories, catalogs, and tags. It seems like it would result in a lot of queries.
But if it's quick enough like you said, I'm fine with it for now.
There was a problem hiding this comment.
@ewaterman yeah, since the results are paginated, it's not that slow. The slowest part of any of those queries is the part when the view is re-built.
As soon as the PR is approved I will prepare somewhat a description of the endpoint with avg times. Anyway, it was not more than 3s in any of the scenarios.
| class CycleCountService { | ||
|
|
||
| List<CycleCountCandidate> getCandidates(CycleCountCandidateFilterCommand command, String facilityId) { | ||
| if (command.hasErrors()) { |
There was a problem hiding this comment.
👍 for the way you've set up the command to be validated at the start
There was a problem hiding this comment.
commands are validated while being bound, so here I'm only checking if it contains errors (as you can see, I did not run the command.validate() - this is run while binding the command).
| if (command.hasErrors()) { | ||
| throw new ValidationException("Invalid params", command.errors) | ||
| } | ||
| Location facility = Location.read(facilityId) |
There was a problem hiding this comment.
I assume "read" is like find but for read-only. Seems like we should be doing this more often 👍
What kind of exception is thrown if the location does not exist? Is it a 500? Maybe we should wrap it in a try/catch so that we can return a 400 or 404. We probably don't want to have a gross stack trace here.
There was a problem hiding this comment.
For now none exception is thrown (.read returns null if an object is not found). Since we need the location id in the URL, it's a very rare case that the location would not exist. Even if it doesn't, the output would just be:
{
data: [],
totalCount: 0,
}I'm fine with addressing this edge case later, if we are not comfortable with the empty result for non-existing location, which is barely to happen.

✨ Description of Change
Link to GitHub issue or Jira ticket:
Description:
To be added tomorrow
📷 Screenshots & Recordings (optional)