Skip to content

OBPIH-7529 select multiple origins on request details report#5572

Merged
ewaterman merged 4 commits intodevelopfrom
ft/OBPIH-7529-multi-products-request-report
Oct 30, 2025
Merged

OBPIH-7529 select multiple origins on request details report#5572
ewaterman merged 4 commits intodevelopfrom
ft/OBPIH-7529-multi-products-request-report

Conversation

@ewaterman
Copy link
Member

✨ 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)

Screenshot from 2025-10-27 15-34-02

@ewaterman ewaterman self-assigned this Oct 27, 2025
@github-actions github-actions bot added type: feature A new piece of functionality for the app domain: frontend Changes or discussions relating to the frontend UI domain: backend Changes or discussions relating to the backend server labels Oct 27, 2025
@codecov
Copy link

codecov bot commented Oct 27, 2025

Codecov Report

❌ Patch coverage is 1.42857% with 69 lines in your changes missing coverage. Please review.
✅ Project coverage is 8.49%. Comparing base (1bb7314) to head (206b20c).
⚠️ Report is 169 commits behind head on develop.

Files with missing lines Patch % Lines
.../pih/warehouse/data/HibernateSessionService.groovy 2.85% 34 Missing ⚠️
...ih/warehouse/forecasting/ForecastingService.groovy 0.00% 17 Missing ⚠️
src/main/groovy/util/RequestParamsUtil.groovy 0.00% 11 Missing ⚠️
src/main/groovy/util/StringUtil.groovy 0.00% 7 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

* For example: Product.getByName(name) or Product.executeQuery(...).
*/
@Transactional
class HibernateService {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just call this

setParameters(query, params)

or

bindParameters(query, params)

I think i prefer bindParameters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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=[:]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

@ewaterman ewaterman Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment on lines 46 to 47
Integer pageSize=null,
Integer offset=null) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may consider using PaginationParams here


class ForecastingService {

HibernateSessionService hibernateSessionService
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

@ewaterman ewaterman merged commit 59e3efb into develop Oct 30, 2025
7 checks passed
@ewaterman ewaterman deleted the ft/OBPIH-7529-multi-products-request-report branch October 30, 2025 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: backend Changes or discussions relating to the backend server domain: frontend Changes or discussions relating to the frontend UI type: feature A new piece of functionality for the app

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants