OBPIH-6898 Cycle count start recount API#5051
Conversation
|
|
||
| CycleCountRequest cycleCountRequest | ||
|
|
||
| Integer countIndex |
There was a problem hiding this comment.
since I split the start count and start recount into separate APIs, we don't even need to specify countIndex on the start count API anymore, we can just assume countIndex==0
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #5051 +/- ##
============================================
- Coverage 7.83% 7.83% -0.01%
Complexity 884 884
============================================
Files 626 629 +3
Lines 42871 42911 +40
Branches 10385 10392 +7
============================================
+ Hits 3359 3362 +3
- Misses 39011 39048 +37
Partials 501 501 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| import org.springframework.validation.BeanPropertyBindingResult | ||
| import org.springframework.validation.Errors | ||
|
|
||
| class BatchCommandUtils { |
There was a problem hiding this comment.
we've been adding a lot of batch commands so I figured I'd move this validation logic to a common place to avoid the duplicate code
There was a problem hiding this comment.
thank you for that. I considered doing the same thing if I had to validate the batch in one more API.
| } | ||
|
|
||
| // We need to build the errors manually so that we can group them all together. | ||
| Errors errors = new BeanPropertyBindingResult(batch, batchPropertyName) |
There was a problem hiding this comment.
isn't it worth creating an enum for batchPropertyName?
There was a problem hiding this comment.
this is the name of the List field in the parent command so I don't know if an enum makes sense here
| cycleCountStartCommand.countIndex.mustEqualZero=Count index must equal 0 for a new cycle count | ||
| cycleCountStartRecountCommand.cycleCountRequest.noCycleCountFound= | ||
| cycleCountStartRecountCommand.cycleCountRequest.invalidCycleCountStatus=Recount cannot be started when cycle count status is ({3}) | ||
| cycleCountStartRecountCommand.countIndex.invalid=Count index ({3}) is invalid for recount |
There was a problem hiding this comment.
Users will see this error. Is the "count index" understandable for the users?
There was a problem hiding this comment.
yeah we don't expose this field to users so if this error is triggered it means we have a bug and there's nothing the user can do to fix it. I don't think there's a message we could include here that would actually help users. We'd just need to fix the bug. It shouldn't happen though since we hard code the count index to 1 for recounts.
|
|
||
| // If there are already items for the requested count index, simply return the count as it is since the recount | ||
| // has already been started. We do this (instead of throwing an error) because it's convenient for the frontend. | ||
| if (cycleCount.cycleCountItems.any(){ it.countIndex == command.countIndex }) { |
There was a problem hiding this comment.
I think the () after .any are unnecessary. It should be enough to do: .any { it.countIndex == command.countIndex }
| cycleCount.addToCycleCountItems(cycleCountItem) | ||
| } | ||
|
|
||
| if (!cycleCount.save()) { |
There was a problem hiding this comment.
I think it would be better to call .validate(), so to say:
if (!cycleCount.validate())
I am not a big fan of calling .save() explicitly on things that are already known for the hibernate persistence context (are not brand new instances).
Remember though, that you would have to save the initialized cycle count items above explicitly, because they are brand new items that are now saved thanks to the cascading behavior.
There was a problem hiding this comment.
in general I agree that simply calling validate is enough. If in this case it's as you say we need to call save on each of the items, I'm not sure what approach I prefer. Calling save only when needed (hopefully) avoids potential GORM weirdness, but I do like simply calling save on the parent cycle count to reinforce the idea that saving happens from the parent down.
I'll mess around with it
There was a problem hiding this comment.
I wasn't able to figure out what the performance difference was for each approach (maybe there isn't one) but in this specific scenario where we're initializing a bunch of items in a loop, I think I prefer having just the one save that we call at the end vs needing to call save on each of the items individually.
but yes I agree with you that validate is typically the better option for existing entities.
There was a problem hiding this comment.
I won't force the change, but I would vote for saving each of the items individually, instead of relying on the cascade behavior. The reason I'm so opposed to the cascading and calling .save() explicilty while updating is that once I faced a similar thing in another project and that made the request run over 4 minutes. When I removed the cascading and called save only on new instances, the performance improved from 4 minutes to 2 seconds 🙈 .
Anyway it's rather my loose thought and something we can worry about when we face a problem related to that.
There was a problem hiding this comment.
oh weird. Yeah I do like the idea of not relying on the cascade. Something we can potentially revisit as you say. Especially given all the scary-ness with the hasMany, we should definitely keep a close eye on the performance of these APIs.
| return CycleCountDto.toDto(cycleCount) | ||
| } | ||
|
|
||
| private CycleCountItem initCycleCountItem( |
There was a problem hiding this comment.
maybe it would be better to move this method to the CycleCountItem domain? What do you think?
There was a problem hiding this comment.
I don't know if I want to move it to the domain because the init logic is specific to how we do the count. A new flow in the future might do things a different way and need to init via different fields so we could end up with a bunch of different constructors in the domain, which would be confusing. I tend to like to leave feature-specific flows in the feature service classes.
| import org.springframework.validation.BeanPropertyBindingResult | ||
| import org.springframework.validation.Errors | ||
|
|
||
| class BatchCommandUtils { |
There was a problem hiding this comment.
thank you for that. I considered doing the same thing if I had to validate the batch in one more API.
grails-app/i18n/messages.properties
Outdated
| cycleCountRequestCommand.product.duplicateExists=Cycle count request already exists for this product ({3}) | ||
| cycleCountRequestBatchCommand.requests.duplicateExists=Cycle count request already exists for this/these products ({3}) | ||
| cycleCountStartCommand.countIndex.mustEqualZero=Count index must equal 0 for a new cycle count | ||
| cycleCountStartRecountCommand.cycleCountRequest.noCycleCountFound= |
There was a problem hiding this comment.
the message is empty
awalkowiak
left a comment
There was a problem hiding this comment.
Beside one remaining !cycleCount.save() vs !cycleCount.validate() discussion, it looks good to me
✨ Description of Change
Link to GitHub issue or Jira ticket: https://pihemr.atlassian.net/browse/OBPIH-6898
Description: Implement the start recount API and call it in the frontend. Note that the frontend does not yet navigate to the recount page when start resolution is clicked. That will be added in a separate PR. This API will, like the start count API, insert new cycle count items for each item of the requested product as per product availability, setting a new QoH snapshot for each item.
📷 Screenshots & Recordings (optional)