From 06f635d61e83302115203d2dbe14a6acfc02d506 Mon Sep 17 00:00:00 2001 From: Priyanka-eGov Date: Tue, 28 Jan 2025 13:54:38 +0530 Subject: [PATCH] HCMPRE-2212 making facilityId in plan search a set for multiple drop down search, changes filterMap signature. --- .../repository/impl/PlanRepositoryImpl.java | 1 + .../querybuilder/PlanQueryBuilder.java | 28 +++++---- .../enrichment/PlanFacilityEnricher.java | 6 +- .../src/main/java/digit/util/QueryUtil.java | 57 ++++++++++++++++--- .../models/PlanFacilitySearchCriteria.java | 2 +- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java b/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java index 90cdb199bf..d1e6ca2521 100644 --- a/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java +++ b/health-services/plan-service/src/main/java/digit/repository/impl/PlanRepositoryImpl.java @@ -152,6 +152,7 @@ private List queryDatabaseForPlanIds(PlanSearchCriteria planSearchCriter List preparedStmtList = new ArrayList<>(); String query = planQueryBuilder.getPlanSearchQuery(planSearchCriteria, preparedStmtList); log.info("Plan search query: " + query); + log.info("PreparedStatment List " + preparedStmtList); return jdbcTemplate.query(query, new SingleColumnRowMapper<>(String.class), preparedStmtList.toArray()); } diff --git a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java index 27c53bb9cc..892f87147e 100644 --- a/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java +++ b/health-services/plan-service/src/main/java/digit/repository/querybuilder/PlanQueryBuilder.java @@ -7,10 +7,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; +import java.util.*; @Component public class PlanQueryBuilder { @@ -172,13 +169,22 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< queryUtil.addToPreparedStatement(preparedStmtList, planSearchCriteria.getJurisdiction()); } - if(!CollectionUtils.isEmpty(planSearchCriteria.getFiltersMap())) { - queryUtil.addClauseIfRequired(builder, preparedStmtList); - builder.append(" additional_details @> CAST( ? AS jsonb )"); - String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap()); - preparedStmtList.add(partialQueryJsonString); + if (!CollectionUtils.isEmpty(planSearchCriteria.getFiltersMap())) { + Map> filtersMap = planSearchCriteria.getFiltersMap(); + for (String key : filtersMap.keySet()) { + if ("facilityId".equals(key)) { + String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList); + builder.append(partialQueryJsonString); + } else { + queryUtil.addClauseIfRequired(builder, preparedStmtList); + builder.append(" additional_details @> CAST( ? AS jsonb )"); + String partialQueryJsonString = queryUtil.preparePartialJsonStringFromFilterMap(planSearchCriteria.getFiltersMap(), preparedStmtList); + preparedStmtList.add(partialQueryJsonString); + } + } } + StringBuilder countQuery = new StringBuilder(); if (isCount) { @@ -191,7 +197,7 @@ private String buildPlanSearchQuery(PlanSearchCriteria planSearchCriteria, List< if (isStatusCount) { return PLAN_STATUS_COUNT_QUERY.replace("{INTERNAL_QUERY}", builder); } - + System.out.println(preparedStmtList); return builder.toString(); } @@ -205,7 +211,7 @@ private String getPaginatedQuery(String query, PlanSearchCriteria planSearchCrit // Append limit paginatedQuery.append(" LIMIT ? "); preparedStmtList.add(ObjectUtils.isEmpty(planSearchCriteria.getLimit()) ? config.getDefaultLimit() : planSearchCriteria.getLimit()); - + System.out.println(preparedStmtList); return paginatedQuery.toString(); } diff --git a/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java b/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java index c204f54c69..fccb2de96d 100644 --- a/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java +++ b/health-services/plan-service/src/main/java/digit/service/enrichment/PlanFacilityEnricher.java @@ -192,16 +192,16 @@ public void enrichSearchRequest(PlanFacilitySearchRequest planFacilitySearchRequ PlanFacilitySearchCriteria planFacilitySearchCriteria = planFacilitySearchRequest.getPlanFacilitySearchCriteria(); // Filter map for filtering facility meta data present in additional details - Map> filtersMap = new LinkedHashMap<>(); + Map filtersMap = new LinkedHashMap<>(); // Add facility status as a filter if present in search criteria if(!ObjectUtils.isEmpty(planFacilitySearchCriteria.getFacilityStatus())) { - filtersMap.put(FACILITY_STATUS_SEARCH_PARAMETER_KEY, Collections.singleton(planFacilitySearchCriteria.getFacilityStatus())); + filtersMap.put(FACILITY_STATUS_SEARCH_PARAMETER_KEY, planFacilitySearchCriteria.getFacilityStatus()); } // Add facility type as a filter if present in search criteria if(!ObjectUtils.isEmpty(planFacilitySearchCriteria.getFacilityType())) { - filtersMap.put(FACILITY_TYPE_SEARCH_PARAMETER_KEY, Collections.singleton(planFacilitySearchCriteria.getFacilityType())); + filtersMap.put(FACILITY_TYPE_SEARCH_PARAMETER_KEY, planFacilitySearchCriteria.getFacilityType()); } if(!CollectionUtils.isEmpty(filtersMap)) diff --git a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java index 3333400e3f..ecdc7c075e 100644 --- a/health-services/plan-service/src/main/java/digit/util/QueryUtil.java +++ b/health-services/plan-service/src/main/java/digit/util/QueryUtil.java @@ -10,10 +10,7 @@ import org.springframework.util.ObjectUtils; import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.IntStream; import static digit.config.ServiceConstants.DOT_REGEX; @@ -102,7 +99,7 @@ public String addOrderByClause(String query, String orderByClause) { * @param filterMap * @return */ - public String preparePartialJsonStringFromFilterMap(Map> filterMap) { + public String preparePartialJsonStringFromFilterMap(Map filterMap) { Map queryMap = new HashMap<>(); filterMap.keySet().forEach(key -> { @@ -121,6 +118,48 @@ public String preparePartialJsonStringFromFilterMap(Map> fil return partialJsonQueryString; } + public String preparePartialJsonStringFromFilterMap(Map> filterMap, List preparedStmtList) { + Map queryMap = new HashMap<>(); + StringBuilder finalJsonQuery = new StringBuilder(); + + for (String key : filterMap.keySet()) { + // Handle nested keys (dot separator) + if (key.contains(DOT_SEPARATOR)) { + String[] keyArray = key.split(DOT_REGEX); + Map nestedQueryMap = new HashMap<>(); + prepareNestedQueryMap(0, keyArray, nestedQueryMap, String.valueOf(filterMap.get(key))); + queryMap.put(keyArray[0], nestedQueryMap.get(keyArray[0])); + return gson.toJson(queryMap); + } else if ("facilityId".equals(key)) { + Set values = filterMap.get(key); + if (values != null && !values.isEmpty()) { + StringBuilder orClauseBuilder = new StringBuilder(); + + // For each value, add an OR condition with a placeholder for the value + for (String value : values) { + if (orClauseBuilder.length() > 0) { + orClauseBuilder.append(" OR "); + } + // Add the condition for the key-value pair + orClauseBuilder.append("additional_details @> ?::jsonb"); + // Add the actual value in the format { "facilityId": "value" } + preparedStmtList.add("{\"" + key + "\": \"" + value + "\"}"); + } + + // Append the OR clause as part of the AND conditions + finalJsonQuery.append(" AND (").append(orClauseBuilder.toString()).append(") "); + return finalJsonQuery.toString(); // Return the query with OR conditions for facilityId + } + } else { + queryMap.put(key, filterMap.get(key).toString()); + } + } + + return gson.toJson(queryMap); + // Return the dynamically constructed query string + } + + /** * Tail recursive method to prepare n-level nested partial json for queries on nested data in * master data. For e.g. , if the key is in the format a.b.c, it will construct a nested json @@ -129,16 +168,16 @@ public String preparePartialJsonStringFromFilterMap(Map> fil * @param index * @param nestedKeyArray * @param currentQueryMap - * @param values + * @param value */ - private void prepareNestedQueryMap(int index, String[] nestedKeyArray, Map currentQueryMap, Set values) { + private void prepareNestedQueryMap(int index, String[] nestedKeyArray, Map currentQueryMap, String value) { // Return when all levels have been reached. if (index == nestedKeyArray.length) return; // For the final level simply put the value in the map. else if (index == nestedKeyArray.length - 1) { - currentQueryMap.put(nestedKeyArray[index], values); + currentQueryMap.put(nestedKeyArray[index], value); return; } @@ -146,7 +185,7 @@ else if (index == nestedKeyArray.length - 1) { currentQueryMap.put(nestedKeyArray[index], new HashMap<>()); // Make a recursive call to enrich data in next level. - prepareNestedQueryMap(index + 1, nestedKeyArray, (Map) currentQueryMap.get(nestedKeyArray[index]), values); + prepareNestedQueryMap(index + 1, nestedKeyArray, (Map) currentQueryMap.get(nestedKeyArray[index]), value); } /** diff --git a/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java b/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java index bab8d1555f..a5a4e49c42 100644 --- a/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java +++ b/health-services/plan-service/src/main/java/digit/web/models/PlanFacilitySearchCriteria.java @@ -59,6 +59,6 @@ public class PlanFacilitySearchCriteria { private Integer limit = null; @JsonIgnore - private Map> filtersMap = null; + private Map filtersMap = null; }