Skip to content

Commit f8ae56d

Browse files
committed
MAT-10160: update search to filter for reviews
1 parent ae6aa03 commit f8ae56d

12 files changed

Lines changed: 278 additions & 104 deletions

src/main/java/cms/gov/madie/measure/repositories/MeasureSearchService.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ Page<MeasureListDTO> searchMeasuresByCriteria(
2121
String userId,
2222
Pageable pageable,
2323
MeasureSearchCriteria searchCriteria,
24-
List<OwnershipType> ownershipTypes);
24+
List<OwnershipType> ownershipTypes,
25+
boolean isReview);
2526

2627
/**
2728
* Get all the measures(name, version and owner) if they include any version of given library name
@@ -32,4 +33,6 @@ Page<MeasureListDTO> searchMeasuresByCriteria(
3233
List<LibraryUsage> findLibraryUsageByLibraryName(String name);
3334

3435
int countMeasuresByOwnership(boolean isActive, String userId, List<OwnershipType> ownershipTypes);
36+
37+
int countMeasuresByReview(boolean isActive, String userId, List<OwnershipType> ownershipTypes);
3538
}

src/main/java/cms/gov/madie/measure/repositories/MeasureSearchServiceImpl.java

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import cms.gov.madie.measure.utils.SearchUtils;
88
import gov.cms.madie.models.access.RoleEnum;
99
import gov.cms.madie.models.common.OwnershipType;
10+
import gov.cms.madie.models.common.ReviewStatus;
1011
import gov.cms.madie.models.dto.LibraryUsage;
1112
import gov.cms.madie.models.dto.UserDetailsDto;
1213
import gov.cms.madie.models.measure.Measure;
@@ -118,11 +119,12 @@ public Page<MeasureListDTO> searchMeasuresByCriteria(
118119
String userId,
119120
Pageable pageable,
120121
MeasureSearchCriteria measureSearchCriteria,
121-
List<OwnershipType> ownershipTypes) {
122+
List<OwnershipType> ownershipTypes,
123+
boolean isReview) {
122124

123125
// Query 1: find all matching measureSetIds and their match counts
124126
Map<String, MeasureSetMatchCountDTO> matchInfoMap =
125-
findMatchedMeasureSets(userId, measureSearchCriteria, ownershipTypes);
127+
findMatchedMeasureSets(userId, measureSearchCriteria, ownershipTypes, isReview);
126128

127129
List<String> matchedMeasureSetIds = new ArrayList<>(matchInfoMap.keySet());
128130
if (matchedMeasureSetIds.isEmpty()) {
@@ -131,7 +133,7 @@ public Page<MeasureListDTO> searchMeasuresByCriteria(
131133

132134
// Query 2: fetch paginated + sorted results for the matched measure sets
133135
List<FacetDTO> results =
134-
fetchFacetResults(userId, pageable, measureSearchCriteria, matchedMeasureSetIds);
136+
fetchFacetResults(userId, pageable, measureSearchCriteria, matchedMeasureSetIds, isReview);
135137

136138
List<MeasureListDTO> queryResults = results.get(0).getQueryResults();
137139

@@ -169,7 +171,8 @@ public Page<MeasureListDTO> searchMeasuresByCriteria(
169171
private Map<String, MeasureSetMatchCountDTO> findMatchedMeasureSets(
170172
String userId,
171173
MeasureSearchCriteria measureSearchCriteria,
172-
List<OwnershipType> ownershipTypes) {
174+
List<OwnershipType> ownershipTypes,
175+
boolean isReview) {
173176
List<AggregationOperation> aggregationOperations = new ArrayList<>();
174177

175178
LookupOperation lookupOperation = getLookupOperation();
@@ -187,7 +190,7 @@ private Map<String, MeasureSetMatchCountDTO> findMatchedMeasureSets(
187190
aggregationOperations.add(SearchAggregationUtils.addCmsIdDisplayField());
188191
}
189192
if (SearchAggregationUtils.isReviewSearch(measureSearchCriteria)) {
190-
aggregationOperations.addAll(SearchAggregationUtils.getReviewStages());
193+
aggregationOperations.addAll(SearchAggregationUtils.getReviewStages(isReview));
191194
}
192195
SearchUtils.appendAdditionalSearchCriteria(measureCriteria, measureSearchCriteria);
193196
}
@@ -255,7 +258,8 @@ private List<FacetDTO> fetchFacetResults(
255258
String userId,
256259
Pageable pageable,
257260
MeasureSearchCriteria measureSearchCriteria,
258-
List<String> matchedMeasureSetIds) {
261+
List<String> matchedMeasureSetIds,
262+
boolean isReview) {
259263
LookupOperation lookupOperation = getLookupOperation();
260264
UnwindOperation unwindOperation = unwind("measureSet");
261265
ProjectionOperation initialProjection = project().andExclude("testCases", "elmJson");
@@ -266,7 +270,7 @@ private List<FacetDTO> fetchFacetResults(
266270
postMatchPipeline.add(initialProjection);
267271
postMatchPipeline.add(match(Criteria.where("measureSetId").in(matchedMeasureSetIds)));
268272
postMatchPipeline.addAll(getLockStages(userId));
269-
postMatchPipeline.addAll(SearchAggregationUtils.getReviewStages());
273+
postMatchPipeline.addAll(SearchAggregationUtils.getReviewStages(isReview));
270274

271275
// Sort those measures based on active status, version and draft status
272276
// Active measures should come first, then draft measures, then by version
@@ -496,4 +500,48 @@ public int countMeasuresByOwnership(
496500

497501
return results.isEmpty() ? 0 : Integer.parseInt(results.get(0).get("count").toString());
498502
}
503+
504+
@Override
505+
public int countMeasuresByReview(
506+
boolean isActive, String userId, List<OwnershipType> ownershipTypes) {
507+
LookupOperation lookupOperation = getLookupOperation();
508+
Criteria measureCriteria = Criteria.where("active").is(isActive);
509+
510+
Criteria measureSetCriteria = buildMeasureSetCriteria(userId, ownershipTypes);
511+
512+
LookupOperation reviewLookup =
513+
LookupOperation.newLookup()
514+
.from("measureReview")
515+
.localField("measureSetId")
516+
.foreignField("measureSetId")
517+
.as("review");
518+
519+
Criteria reviewCriteria =
520+
new Criteria()
521+
.orOperator(
522+
Criteria.where("review.status").is(ReviewStatus.READY_FOR_REVIEW),
523+
Criteria.where("review.status").is(ReviewStatus.IN_PROGRESS),
524+
Criteria.where("review.status").is(ReviewStatus.COMPLETE));
525+
526+
MatchOperation matchOperation =
527+
(measureSetCriteria != null)
528+
? match(new Criteria().andOperator(measureCriteria, measureSetCriteria, reviewCriteria))
529+
: match(new Criteria().andOperator(measureCriteria, reviewCriteria));
530+
531+
GroupOperation groupOperation = group("measureSetId");
532+
533+
Aggregation aggregation =
534+
newAggregation(
535+
lookupOperation,
536+
reviewLookup,
537+
unwind("review"),
538+
matchOperation,
539+
groupOperation,
540+
group().count().as("count"));
541+
542+
List<Map> results =
543+
mongoTemplate.aggregate(aggregation, Measure.class, Map.class).getMappedResults();
544+
545+
return results.isEmpty() ? 0 : Integer.parseInt(results.get(0).get("count").toString());
546+
}
499547
}

src/main/java/cms/gov/madie/measure/repositories/MeasureSetSearchRepositoryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public List<MeasureListDTO> findMeasuresByMeasureSetId(
5050
aggregationOperations.add(SearchAggregationUtils.addCmsIdDisplayField());
5151
}
5252
if (SearchAggregationUtils.isReviewSearch(measureSearchCriteria)) {
53-
aggregationOperations.addAll(SearchAggregationUtils.getReviewStages());
53+
aggregationOperations.addAll(SearchAggregationUtils.getReviewStages(false));
5454
}
5555
SearchUtils.appendAdditionalSearchCriteria(measureCriteria, measureSearchCriteria);
5656
}

src/main/java/cms/gov/madie/measure/resources/AdminController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,8 @@ public ResponseEntity<Page<MeasureListDTO>> searchMeasuresForUser(
712712
PageRequest.of(page, limit, Sort.by(Sort.Direction.valueOf(direction), sort));
713713

714714
Page<MeasureListDTO> measures =
715-
measureService.getMeasuresByCriteria(searchCriteria, ownershipTypes, pageReq, username);
715+
measureService.getMeasuresByCriteria(
716+
searchCriteria, ownershipTypes, false, pageReq, username);
716717
return ResponseEntity.ok(measures);
717718
}
718719
}

src/main/java/cms/gov/madie/measure/resources/MeasureController.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public ResponseEntity<Page<MeasureListDTO>> getMeasures(
9292
PageRequest.of(page, limit, Sort.by(Sort.Direction.valueOf(direction), sort));
9393
// TODO Remove parameter "measures" when either measureSearch or EditTestsOnVersionedMeasure is
9494
// removed.
95-
measures = measureService.getMeasuresByCriteria(null, ownershipTypes, pageReq, username);
95+
measures = measureService.getMeasuresByCriteria(null, ownershipTypes, false, pageReq, username);
9696
return ResponseEntity.ok(measures);
9797
}
9898

@@ -112,6 +112,15 @@ public ResponseEntity<Map<String, Integer>> getCounts(Principal principal) {
112112
measureService.countMeasuresByOwnership(
113113
true, principal.getName().toLowerCase(), List.of(OwnershipType.ALL)));
114114

115+
results.put(
116+
"ownedReviews",
117+
measureService.countMeasuresByReview(
118+
true, principal.getName().toLowerCase(), List.of(OwnershipType.OWNED)));
119+
results.put(
120+
"allReviews",
121+
measureService.countMeasuresByReview(
122+
true, principal.getName().toLowerCase(), List.of(OwnershipType.ALL)));
123+
115124
return ResponseEntity.ok(results);
116125
}
117126

@@ -394,6 +403,7 @@ public ResponseEntity<Measure> deleteStratification(
394403
public ResponseEntity<Page<MeasureListDTO>> measureSearchByCriteria(
395404
Principal principal,
396405
@RequestParam(name = "ownershipTypes", required = false) List<OwnershipType> ownershipTypes,
406+
@RequestParam(name = "isReview", required = false) boolean isReview,
397407
@RequestBody(required = false) MeasureSearchCriteria searchCriteria,
398408
@RequestParam(required = false, defaultValue = "10", name = "limit") int limit,
399409
@RequestParam(required = false, defaultValue = "0", name = "page") int page,
@@ -404,7 +414,8 @@ public ResponseEntity<Page<MeasureListDTO>> measureSearchByCriteria(
404414
PageRequest.of(page, limit, Sort.by(Sort.Direction.valueOf(direction), sort));
405415

406416
Page<MeasureListDTO> measures =
407-
measureService.getMeasuresByCriteria(searchCriteria, ownershipTypes, pageReq, username);
417+
measureService.getMeasuresByCriteria(
418+
searchCriteria, ownershipTypes, isReview, pageReq, username);
408419

409420
return ResponseEntity.ok(measures);
410421
}

src/main/java/cms/gov/madie/measure/services/MeasureService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,10 +717,11 @@ public List<String> getAllActiveMeasureIds(boolean draftOnly) {
717717
public Page<MeasureListDTO> getMeasuresByCriteria(
718718
MeasureSearchCriteria searchCriteria,
719719
List<OwnershipType> ownershipTypes,
720+
boolean isReview,
720721
Pageable pageReq,
721722
String username) {
722723
return measureRepository.searchMeasuresByCriteria(
723-
username, pageReq, searchCriteria, ownershipTypes);
724+
username, pageReq, searchCriteria, ownershipTypes, isReview);
724725
}
725726

726727
protected void updateReferences(MeasureMetaData metaData) {
@@ -991,6 +992,11 @@ public int countMeasuresByOwnership(
991992
return measureRepository.countMeasuresByOwnership(isActive, userId, ownershipTypes);
992993
}
993994

995+
public int countMeasuresByReview(
996+
boolean isActive, String userId, List<OwnershipType> ownershipTypes) {
997+
return measureRepository.countMeasuresByReview(isActive, userId, ownershipTypes);
998+
}
999+
9941000
public List<String> transferMeasures(
9951001
List<String> measureIds,
9961002
String harpId,

src/main/java/cms/gov/madie/measure/utils/SearchAggregationUtils.java

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,60 @@
44
import gov.cms.madie.models.common.ReviewStatus;
55
import org.apache.commons.collections4.CollectionUtils;
66
import org.bson.Document;
7-
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
8-
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
9-
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
10-
import org.springframework.data.mongodb.core.aggregation.ComparisonOperators;
11-
import org.springframework.data.mongodb.core.aggregation.ConditionalOperators;
12-
import org.springframework.data.mongodb.core.aggregation.ConvertOperators;
7+
import org.springframework.data.mongodb.core.aggregation.*;
138
import org.springframework.data.mongodb.core.query.Criteria;
149

10+
import java.util.ArrayList;
1511
import java.util.Arrays;
1612
import java.util.Collections;
1713
import java.util.List;
1814

19-
import static org.springframework.data.mongodb.core.aggregation.Aggregation.addFields;
20-
import static org.springframework.data.mongodb.core.aggregation.Aggregation.lookup;
21-
import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
15+
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
16+
import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.*;
2217

2318
public class SearchAggregationUtils {
2419

25-
public static List<AggregationOperation> getReviewStages() {
26-
return Arrays.asList(
27-
addFields()
28-
.addField("measureIdString")
29-
.withValue(ConvertOperators.ToString.toString("$_id"))
30-
.build(),
31-
32-
lookup("measureReview", "measureIdString", "measureId", "review"),
33-
34-
addFields()
35-
.addField("reviewStatus")
36-
.withValue(
37-
ConditionalOperators.when(
38-
ComparisonOperators.Eq.valueOf(
39-
ArrayOperators.ArrayElemAt.arrayOf("$review.status").elementAt(0))
40-
.equalToValue(ReviewStatus.READY_FOR_REVIEW.name()))
41-
.then("Ready")
42-
.otherwise(""))
43-
.build());
20+
public static List<AggregationOperation> getReviewStages(boolean isReview) {
21+
22+
List<AggregationOperation> reviewStages =
23+
new ArrayList<>(
24+
Arrays.asList(
25+
lookup("measureReview", "measureSetId", "measureSetId", "review"),
26+
addFields()
27+
.addField("reviewStatus")
28+
.withValue(
29+
switchCases(
30+
Switch.CaseOperator.when(
31+
ComparisonOperators.Eq.valueOf(
32+
ArrayOperators.ArrayElemAt.arrayOf("$review.status")
33+
.elementAt(0))
34+
.equalToValue(ReviewStatus.READY_FOR_REVIEW.name()))
35+
.then("Ready"),
36+
Switch.CaseOperator.when(
37+
ComparisonOperators.Eq.valueOf(
38+
ArrayOperators.ArrayElemAt.arrayOf("$review.status")
39+
.elementAt(0))
40+
.equalToValue(ReviewStatus.IN_PROGRESS.name()))
41+
.then("In Progress"),
42+
Switch.CaseOperator.when(
43+
ComparisonOperators.Eq.valueOf(
44+
ArrayOperators.ArrayElemAt.arrayOf("$review.status")
45+
.elementAt(0))
46+
.equalToValue(ReviewStatus.COMPLETE.name()))
47+
.then("Complete"))
48+
.defaultTo(""))
49+
.build()));
50+
if (isReview) {
51+
52+
reviewStages.add(
53+
match(
54+
new Criteria()
55+
.orOperator(
56+
Criteria.where("reviewStatus").is("Ready"),
57+
Criteria.where("reviewStatus").is("In Progress"),
58+
Criteria.where("reviewStatus").is("Complete"))));
59+
}
60+
return reviewStages;
4461
}
4562

4663
public static boolean isReviewSearch(MeasureSearchCriteria measureSearchCriteria) {

0 commit comments

Comments
 (0)