OBPIH-6585 Make code a required field when creating/editing location types#4968
Conversation
|
I verified that the following scenario works:
|
| </td> | ||
| <td valign="top" class="value ${hasErrors(bean: locationTypeInstance, field: 'description', 'errors')}"> | ||
| <g:select name="locationTypeCode" class="chzn-select-deselect" from="${org.pih.warehouse.core.LocationTypeCode.list()}" | ||
| noSelection="['':'']" |
There was a problem hiding this comment.
As a reminder, removing this line will default the selection to the first element in LocationTypeCode,list() (which is DEPOT)
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #4968 +/- ##
============================================
+ Coverage 7.68% 7.70% +0.01%
- Complexity 833 842 +9
============================================
Files 610 610
Lines 42521 42521
Branches 10315 10315
============================================
+ Hits 3268 3276 +8
+ Misses 38773 38766 -7
+ Partials 480 479 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
kchelstowski
left a comment
There was a problem hiding this comment.
I feel ok with the code, but I have a doubt if it's a good time to proceed with such change now. I'm worried about some existing data etc - I know you've added the default value, but I don't know if there are any edge cases where it would break something.
awalkowiak
left a comment
There was a problem hiding this comment.
I am not sure about these changes, on one hand these makes sense, but I am not sure about the DEFAULT location type code (Imho it could be just empty string). I'd like to get an opinion from @jmiranda. Plus this feels like something that does not to be released in 0.9.3? The immediate fix could be one of these:
- Manual data fix in db (not sure if this makes sense, but we could take a look what was the fix before in the https://pihemr.atlassian.net/browse/OBPIH-5256
- Make it nullable false, but blank true and allow empty strings there
- On the
buildLocationDimensioninsert, to do a fallback to empty string of something to not break due to null - Make nullable location type code on the location dimension for now.
|
marking as do not merge for now since we decided to resolve this one after we cut the 0.9.3 release |
| class="value ${hasErrors(bean: locationTypeInstance, field: 'description', 'errors')}"> | ||
| <g:select name="locationTypeCode" class="chzn-select-deselect" | ||
| from="${org.pih.warehouse.core.LocationTypeCode.list()}" | ||
| noSelection="['': '']" |
There was a problem hiding this comment.
Removing this property means that the first one from the list is picked automatically or how is it working right now?
There was a problem hiding this comment.
yeah that's right. The first element of LocationTypeCode.list(), which is DEPOT. I can undo this change if we want, but not selecting a value throws us to an ugly error page
There was a problem hiding this comment.
Thinking about this more, I would actually prefer the default to be empty and for the form submission to return and display a validation error for blank/null.
Can you post a screenshot of the ugly page (I assume this is the exception stacktrace) so I can figure out the best way to handle it?
There was a problem hiding this comment.
I agree it's probably better to default to empty and just handle the error better.
This is old gsp pages though so I don't know the best way to do that. Do we even have nice error handling at all for these pages? If it's not a simple fix, maybe it's fine to just leave it with the messy error given that the goal is to eventually migrate everything over to react... idk
There was a problem hiding this comment.
@ewaterman the reason for such error is that the data services throw validation exception when validation didn't pass.
It works the same way as the .save(failOnError: true) would work.
Regular .save() returns null if the validation didn't pass.
On GSP pages we usually tend to handle such cases like that:
if (x.validate() && x.save()) {
render(view: ...)
return
}
// If error occured
render(view: ...)
and then inside view:
<g:hasErrors bean="${x}">
<div class="errors" role="alert" aria-label="error-message">
<g:renderErrors bean="${x}" as="list" />
</div>
</g:hasErrors>
and the errors are listed in user-friendly way.
Since data service's .save() throws en error, you'd have to wrap that in try/catch clause instead, but I'm not a fan of try/catch clause, because there were some inconsistencies in transaction rollback, but I do not remember now if it was Grails 1 or Grails 3 thing (would have to find our discussions from the past).
There was a problem hiding this comment.
Thanks for the detailed explanation. I looked into it and it's actually a really simple fix. It does have the frontend error processing that you suggested Kacper. The thing that was missing was the x.validate() step. Changing the code to the following works:
if (locationTypeInstance.validate() && locationTypeDataService.save(locationTypeInstance)) {
flash.message = "${warehouse.message(code: 'default.updated.message', args: [...])}"
redirect(action: "list", id: locationTypeInstance.id)
}
else {
render(view: "edit", model: [locationTypeInstance: locationTypeInstance])
}
src/test/groovy/unit/org/pih/warehouse/core/LocationControllerSpec.groovy
Outdated
Show resolved
Hide resolved
src/test/groovy/unit/org/pih/warehouse/core/LocationControllerSpec.groovy
Outdated
Show resolved
Hide resolved
src/test/groovy/unit/org/pih/warehouse/core/LocationControllerSpec.groovy
Outdated
Show resolved
Hide resolved
src/test/groovy/unit/org/pih/warehouse/core/LocationControllerSpec.groovy
Outdated
Show resolved
Hide resolved
|
As a refresher for the review (since it has been a while), the main change is to make LocationType.locationTypeCode non-nullable. As a safety measure, I also migrate any existing nulls to use DEFAULT. There shouldn't be any location types with a null code (we don't have any in our environments) since it doesn't really make sense for it to be null, but the migration is there just in case any other implementations have it. Artur suggested we use an empty/blank value instead of DEFAULT. I'm okay with this, but in the frontend, that would allow users to not select a value for location type code from the dropdown. Because all location types should have a code, I'm not sure this is the behaviour we want. I think it's better to explicitly fail to the user and force them to pick a code. Location types with a null/DEFAULT/blank value should need to be fixed because they can cause unexpected behaviour in the system, so I think we shouldn't allow creating new types without a code. I suppose we could create a LocationTypeCommand object (right now the controller just serializes directly to the LocationType domain) that has |
jmiranda
left a comment
There was a problem hiding this comment.
This looks good to me. The only issue I found was that if somehow the location type code was empty string or some invalid value (i.e. INVALID), you'd get redirected to the exception page when attempting to manage location types.
Not sure how likely that scenario is so just something to consider if we encounter a support request.



✨ Description of Change
Link to GitHub issue or Jira ticket: https://pihemr.atlassian.net/browse/OBPIH-6585
Description:
LocationType.locationTypeCodeis currently a nullable field, butLocationDimension.locationTypeCodeis a non-nullable field. If we ever have a location type with a null location type code, it causes column constraint failures when generating location dimensions for all locations and causes the whole action to fail.This change is to make
LocationType.locationTypeCodenon-nullable.Originally implemented in: #4755