OBPIH-7529 select multiple origins on request details report#5572
OBPIH-7529 select multiple origins on request details report#5572
Conversation
grails-app/services/org/pih/warehouse/forecasting/ForecastingService.groovy
Show resolved
Hide resolved
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #5572 +/- ##
============================================
- Coverage 9.12% 8.49% -0.64%
+ Complexity 1170 1114 -56
============================================
Files 701 709 +8
Lines 45281 45511 +230
Branches 10851 10894 +43
============================================
- Hits 4131 3865 -266
- Misses 40497 41071 +574
+ Partials 653 575 -78 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
grails-app/services/org/pih/warehouse/forecasting/ForecastingService.groovy
Show resolved
Hide resolved
| * For example: Product.getByName(name) or Product.executeQuery(...). | ||
| */ | ||
| @Transactional | ||
| class HibernateService { |
There was a problem hiding this comment.
HibernateService feels too broad. Maybe HibernateSessionService (if we're going to support both queries as well as inserts/updates/deletes) or HibernateQueryService (if it's for read-only queries).
If we ever plan to support different types of these services then maybe something like PersistenceService, PersistenceSessionService, or DatabaseSessionService as the interface (doesn't feel right though). And then maybe HibernateSessionService or HibernatePersistenceService as the impl. And the SQL query methods from the DataService (or wherever I put those) can move to something like a SqlPersistenceSessionService.
There was a problem hiding this comment.
I'll rename to HibernateSessionService. I don't think we currently have a need to support multiple approaches (we'll likely prefer this service over DataService going forward) but it's a good idea to allow the potential to switch in the future if needed. Maybe we'd want to start using spring jdbctemplate for whatever reason. I'll look into adding an interface for it.
| */ | ||
| NativeQuery createNativeQuery(String sql, Map<String, Object> params=[:]) { | ||
| NativeQuery query = currentSession.createNativeQuery(sql) | ||
| return setParamsOnQuery(query, params) |
There was a problem hiding this comment.
Just call this
setParameters(query, params)
or
bindParameters(query, params)
I think i prefer bindParameters.
There was a problem hiding this comment.
I chose setParameters because that's what the underlying Query methods are called
| query.setParameterList(key, value) | ||
| break | ||
| case null: | ||
| break // Ignore null values because they'll cause errors. |
There was a problem hiding this comment.
We should probably discuss this. I haven't really thought it through but as a developer I might get annoyed if one of my filters isn't filtering results. So I might expect this to be mapped to an IS NULL or maybe throw an exception.
There was a problem hiding this comment.
yeah that's fair. Maybe the simplest thing to do for now is just throw an exception
| * Map params = ["statuses", statuses, "name", name] | ||
| * List<Map<String, Object>> result = hibernateService.list(sql, params) | ||
| */ | ||
| List<Map<String, Object>> list(String sql, Map<String, Object> params=[:]) { |
There was a problem hiding this comment.
I know we don't need it now, but it might be nice to add all the methods we might need.
def executeUpdate(String sql, Map params = [:]) {
return createNativeQuery(sql, params).executeUpdate()
}
def uniqueResult(String sql, Map params = [:]) {
return createNativeQuery(sql, params).uniqueResult()
}
And we might want to have special handling for pagination. Not sure if the list method is going to handle that explicitly, so check for max, offset and apply appropriately to the query.
There was a problem hiding this comment.
I considered adding them in now, but decided against it because I didn't have a use case for those scenarios and so wouldn't be able to test them. What I can do is add those methods to the interface and then just throw not implemented exceptions so that when we eventually need them, we can implement them (as you described).
We can do pagination via:
if (paginate) {
query.setFirstResult(command.offset).setMaxResults(command.max)
}
I left it out for now since I didn't need it but I'll give it some consideration
|
|
||
| class ForecastingService { | ||
|
|
||
| HibernateSessionService hibernateSessionService |
There was a problem hiding this comment.
I tried for a while to make this use the PersistenceService interface but it wouldn't autowire in HibernateSessionService. According to the docs that I looked at it should have worked because I have the @Primary annotation on HibernateSessionService so I'm not sure...
There was a problem hiding this comment.
That's really weird, we should investigate that. You could check if you use @Qualifier if it would autowire then, but still we shouldn't need to do that.....
Maybe interfaces don't become a Grails bean automatically and we have to do more things explicitly?
There was a problem hiding this comment.
I think I figured it out. If I add the @Autowired annotation, it works. Maybe there's some Grails weirdness going on that makes it unable to resolve the bean so we need to rely on spring 🤷
| * If querying a domain object, use Spring Data's Repository pattern or GORM methods (provided by GormEntity) instead. | ||
| * For example: Product.getByName(name) or Product.executeQuery(...). | ||
| */ | ||
| @Primary |
There was a problem hiding this comment.
I assume the Primary annotation is added in advance so that if we ever create a new implementation of that interface, we'll autowire this one?
I'm asking because it feels like currently it's redundant.
There was a problem hiding this comment.
yup it does nothing now, but it's an easy way for us in the future to switch to a different implementation if needed. I'll remove it for now though for clarity
| Integer pageSize=null, | ||
| Integer offset=null) { |
There was a problem hiding this comment.
You may consider using PaginationParams here
|
|
||
| class ForecastingService { | ||
|
|
||
| HibernateSessionService hibernateSessionService |
There was a problem hiding this comment.
That's really weird, we should investigate that. You could check if you use @Qualifier if it would autowire then, but still we shouldn't need to do that.....
Maybe interfaces don't become a Grails bean automatically and we have to do more things explicitly?
✨ Description of Change
Link to GitHub issue or Jira ticket: https://pihemr.atlassian.net/browse/OBPIH-7529
Description: Allow multiple origins (ie fulfilling locations) to be selected on the request details report. As a part of this change I implemented the HibernateService for use when making native queries when we don't have a Grails domain to work off of.
📷 Screenshots & Recordings (optional)