Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Filter events by existing data element [DHIS2-15954] #19760

Merged
merged 7 commits into from
Jan 28, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,12 @@ private FileResource getFileResourceMetadata(UID eventUid, UID dataElementUid)
"this must be a bug in how the EventOperationParams are built");
}
if (events.getItems().isEmpty()) {
throw new NotFoundException(Event.class, eventUid);
throw new NotFoundException(
"Event "
+ eventUid.getValue()
+ " with data element "
+ dataElementUid.getValue()
+ " could not be found.");
}
Event event = events.getItems().get(0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,6 @@ public EventQueryParams orderBy(String field, SortDirection direction) {
/** Order by the given data element {@code de} in given sort {@code direction}. */
public EventQueryParams orderBy(DataElement de, SortDirection direction) {
this.order.add(new Order(de, direction));
this.dataElements.putIfAbsent(de, new ArrayList<>());
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -893,16 +893,8 @@ private String getEventSelectQuery(
.append(COLUMN_EVENT_ATTRIBUTE_OPTION_COMBO_NAME)
.append(", coc_agg.attributevalues as ")
.append(COLUMN_EVENT_ATTRIBUTE_OPTION_COMBO_ATTRIBUTE_VALUES)
.append(", coc_agg.co_values AS co_values, coc_agg.co_count AS option_size, ");

for (Order order : params.getOrder()) {
if (order.getField() instanceof TrackedEntityAttribute tea)
selectBuilder
.append(quote(tea.getUid()))
.append(".value AS ")
.append(tea.getUid())
.append("_value, ");
}
.append(", coc_agg.co_values AS co_values, coc_agg.co_count AS option_size, ")
.append(addOrderFieldsToSelectClause(params.getOrder()));

return selectBuilder
.append(
Expand All @@ -928,6 +920,32 @@ private String getEventSelectQuery(
.toString();
}

private String addOrderFieldsToSelectClause(List<Order> orders) {
muilpp marked this conversation as resolved.
Show resolved Hide resolved
StringBuilder selectBuilder = new StringBuilder();

for (Order order : orders) {
if (order.getField() instanceof TrackedEntityAttribute tea) {
teleivo marked this conversation as resolved.
Show resolved Hide resolved
selectBuilder
.append(quote(tea.getUid()))
.append(".value AS ")
.append(tea.getUid())
.append("_value, ");
} else if (order.getField() instanceof DataElement de) {
final String dataValueValueSql = "ev.eventdatavalues #>> '{" + de.getUid() + ", value}'";
selectBuilder
.append(
de.getValueType().isNumeric()
? castToNumber(dataValueValueSql)
: lower(dataValueValueSql))
.append(" as ")
.append(de.getUid())
.append(", ");
}
}

return selectBuilder.toString();
}

private boolean checkForOwnership(EventQueryParams params) {
return Optional.ofNullable(params.getProgram())
.filter(
Expand Down Expand Up @@ -1444,6 +1462,11 @@ private StringBuilder dataElementAndFiltersSql(
}
}
}
} else {
eventDataValuesWhereSql.append(hlp.whereAnd());
eventDataValuesWhereSql.append(" (ev.eventdatavalues ?? '");
eventDataValuesWhereSql.append(deUid);
eventDataValuesWhereSql.append("')");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ void shouldKeepExistingAttributeFiltersWhenOrderingByAttribute() {
}

@Test
void shouldAddDataElementToOrderAndDataElementsWhenOrderingByDataElement() {
void shouldAddDataElementToOrderButNotToDataElementsWhenOrderingByDataElement() {
EventQueryParams params = new EventQueryParams();

params.orderBy(de1, SortDirection.ASC);

assertEquals(List.of(new Order(de1, SortDirection.ASC)), params.getOrder());
assertEquals(Map.of(de1, List.of()), params.getDataElements());
assertTrue(params.getDataElements().isEmpty());
Copy link
Contributor

Choose a reason for hiding this comment

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

use assertIsEmpty

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is a Map, not a Collection, that's why I didn't use it
I didn't deem it necessary to create a helper method for this one

assertFalse(params.hasDataElementFilter());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.io.IOException;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -590,6 +591,25 @@ void testExportEventsWhenFilteringByNumericDataElements()
assertContainsOnly(List.of("D9PbzJY8bJM"), events);
}

@Test
void shouldFilterByEventsWithGivenDataValuesWhenFilterContainsDataElementUIDsOnly()
throws ForbiddenException, BadRequestException {
EventOperationParams params =
EventOperationParams.builder()
.eventParams(EventParams.FALSE)
muilpp marked this conversation as resolved.
Show resolved Hide resolved
.dataElementFilters(
Map.of(
UID.of("GieVkTxp4HH"),
new ArrayList<>(),
UID.of("GieVkTxp4HG"),
new ArrayList<>()))
.build();

List<String> events = getEvents(params);

assertContainsOnly(List.of("kWjSezkXHVp"), events);
}

@Test
void testEnrollmentEnrolledBeforeSetToBeforeFirstEnrolledAtDate()
throws ForbiddenException, BadRequestException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,6 @@ void getDataValuesFileByDataElementIfUserDoesNotHaveReadAccessToDataElement()
event.getEventDataValues().add(dataValue(de, file.getUid()));
manager.update(event);

// this.switchContextToUser(user);
switchContextToUser(user);

GET("/tracker/events/{eventUid}/dataValues/{dataElementUid}/file", event.getUid(), de.getUid())
Expand Down Expand Up @@ -568,6 +567,25 @@ void getDataValuesFileByDataElementIfNoDataValueExists() {

switchContextToUser(user);

assertEquals(
"Event " + event.getUid() + " with data element " + de.getUid() + " could not be found.",
GET(
"/tracker/events/{eventUid}/dataValues/{dataElementUid}/file",
event.getUid(),
de.getUid())
.error(HttpStatus.NOT_FOUND)
.getMessage());
}

@Test
void getDataValuesFileByDataElementIfNoDataValueNull() {
Event event = event(enrollment(trackedEntity()));
DataElement de = dataElement(ValueType.IMAGE);

event.getEventDataValues().add(dataValue(de, null));
manager.flush();
switchContextToUser(user);

assertEquals(
"DataValue for data element " + de.getUid() + " could not be found.",
GET(
Expand Down
Loading