OBPIH-6889 Implement get cycle counts API#4997
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #4997 +/- ##
============================================
+ Coverage 7.65% 7.69% +0.03%
- Complexity 832 846 +14
============================================
Files 609 610 +1
Lines 42543 42586 +43
Branches 10330 10344 +14
============================================
+ Hits 3257 3275 +18
- Misses 38809 38826 +17
- Partials 477 485 +8 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| } | ||
|
|
||
| "/api/facilities/$facilityId/cycle-count-candidates" { | ||
| "/api/facilities/$facilityId/cycle-counts" { |
There was a problem hiding this comment.
as explained quickly on the tech huddle - I didn't know whether to keep the cycle-count-candidates and create cycle-counts even though they would point to the same endpoint, or to have a common one.
I'm up for suggestions.
There was a problem hiding this comment.
yeah it is a bit weird. My other comment suggested using just the one GET /cycle-counts/candidates API for all the tabs.
I get that it's a bit strange since for the other tabs like TO COUNT we could look at it like the primary resource we're fetching is cycle count (and we're joining candidate information to that) but since all tabs need essentially the same information, I think it's fine that they all use the GET candidates API
|
|
||
| def getCandidates(CycleCountCandidateFilterCommand filterParams) { | ||
| List<CycleCountCandidate> candidates = cycleCountService.getCandidates(filterParams, params.facilityId) | ||
| def getCycleCounts(CycleCountCandidateFilterCommand filterParams) { |
There was a problem hiding this comment.
I also don't feel comfortable with both getCandidates and getCycleCounts - we base those on CycleCountCandidate, but we might use the endpoint for different usages - either for get candidates (cycleCountRequest = null) or to get cycle counts (to count tab, to resolve tab, to approve tab).
There was a problem hiding this comment.
yeah this is where the most amount of weirdness happens. However since the response data is structured the same for both pages, I think it's fine to treat this as the original getCandidates (or maybe we can think of a new name that makes the most sense). We should remember that the backend has no knowledge of what the frontend is doing, so the API (and method names) should ideally be reflecting only what the data has (and not what it is being used for). Some other frontend could use the API in a different way.
I'll try to think of a method/API name that makes sense.
There was a problem hiding this comment.
Good point not to think about it in the frontend way. I always end up making that mistake.
I changed the url to /cycle-counts/candidates as suggested and kept the methods with the candidates sufix.
| LEFT OUTER JOIN cycle_count_request ON product.id = cycle_count_request.product_id AND location.id = cycle_count_request.facility_id | ||
| WHERE product_availability.quantity_on_hand > 0 | ||
| GROUP BY location.id, product.id, abc_class | ||
| AND (cycle_count_request.id IS NULL OR (cycle_count_request.status <> 'COMPLETED' AND cycle_count_request.status <> 'CANCELED')) |
There was a problem hiding this comment.
basically we have to join the cycle count request table, but since we won't delete the completed and canceled requests, we need to filter them out in order to have unique result per product/facility pair.
We have a constraint for product/facility pair to be unique, but only if a request is not completed or canceled.
Since the candidates don't need to look into completed and canceled requests, I filtered them out.
There was a problem hiding this comment.
Does the "cycle_count_request.id IS NULL" work if there isn't a cycle count request? I'd assume it'd fail if cycle_count_request is null.
There was a problem hiding this comment.
hmm, why would it fail in your opinion?
We LEFT JOIN the cycle_count_request table, so essentially we take all the rows from the cycle_count_session table, and join the cycle_count_request even if it doesn't exist (so then all the rows from cycle_count_request would be null).
So this check basically does this: return all the records from the cycle_count_session where the cycle count request doesn't exist or its status is not neither COMPLETED nor CANCELED.
There was a problem hiding this comment.
I was thinking too Java-based. You're right about the left join
| eq("cycleCountRequest.status", command.status) | ||
| return | ||
| } | ||
| isNull("cycleCountRequest") |
There was a problem hiding this comment.
e.g.
- for "to count" tab we will filter by
CREATEDstatus - for all products tab we don't provide status, so we want to search for candidates that do not have the cycle count request created
There was a problem hiding this comment.
We also need to filter out requests that are currently in progress. Those shouldn't show up on the all products tab.
There was a problem hiding this comment.
on all products tab we don't provide the status property, hence we would return all candidates that DO NOT have the cycle count request.
There was a problem hiding this comment.
but the all products tab shouldn't show any candidates that have an in progress count. You shouldn't be able to start the count if one is already in progress
There was a problem hiding this comment.
and they won't show, because the cycle count request would already exist for such candidate, so those would be filtered out.
There was a problem hiding this comment.
is that true? Maybe I'm misunderstanding, but for all products tab we don't provide a status and so we do isNull("cycleCountRequest") and fetch only the rows that don't have a request.
I don't want to go in circles about this so if you tested it and it's working, I trust you and we can move on 😆
There was a problem hiding this comment.
We discussed on slack. I'm being silly. This code works.
| } | ||
|
|
||
| "/api/facilities/$facilityId/cycle-count-candidates" { | ||
| "/api/facilities/$facilityId/cycle-counts" { |
There was a problem hiding this comment.
I think this API should still be /cycle-count-candidates (though I'd make it /cycle-count/candidates) since ultimately it is candidates focused. (It's returning List so fundamentally it's about candidates.)
I also wanted to use the GET /cycle-counts API for another purpose: https://pihemr.atlassian.net/wiki/spaces/OB/pages/3332505612/Cycle+Count+Items+API#Get-Cycle-Counts
GET /api/facilities/{facility_id}/cycle-counts?ids=1,2,3
[
{
request: { ... },
cycleCount: {
id: "1",
...other fields...
cycleCountItems: [ ... ],
},
},
...
]
So it's an API for simply fetching cycle counts, their items, and associated requests, which we (might) need when loading the count page for an already in progress count.
I like being able to have the CRUD style endpoints for cycle count using "cycle-counts" as a base resource. That way the /candidates API can stay as its own thing.
- GET /cycle-counts
- GET /cycle-counts/{cycle_count_id}
- GET /cycle-counts/candidates
There was a problem hiding this comment.
(sorry I wrote this before I saw your messages. I didn't refresh the page.)
|
@awalkowiak to unblock the rest of the PRs and the testing, I'm merging this one as it is. If you have any suggestions/change requests, let me know and I will address them separately. |
✨ Description of Change
Link to GitHub issue or Jira ticket:
Description:
📷 Screenshots & Recordings (optional)