Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ public final class EventAnalyticsColumnName {
public static final String ENROLLMENT_GEOMETRY_COLUMN_NAME = "enrollmentgeometry";
public static final String REGISTRATION_OU_COLUMN_NAME = "registrationou";
public static final String ENROLLMENT_OU_COLUMN_NAME = "enrollmentou";
public static final String ENROLLMENT_OU_NAME_COLUMN_NAME = "enrollmentouname";
public static final String TRACKED_ENTITY_GEOMETRY_COLUMN_NAME = "tegeometry";
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
import static lombok.AccessLevel.PRIVATE;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.hisp.dhis.common.DimensionConstants.PERIOD_DIM_ID;
import static org.hisp.dhis.common.DimensionConstants.STATIC_DATE_DIMENSIONS;

import java.util.Set;
import java.util.stream.Stream;
import lombok.NoArgsConstructor;
import org.hisp.dhis.common.EnrollmentAnalyticsQueryCriteria;
Expand All @@ -43,6 +43,20 @@
/** Helper class that provides supportive methods to deal with query criteria and periods. */
@NoArgsConstructor(access = PRIVATE)
public class PeriodCriteriaUtils {

/**
* Date dimensions that get normalized to "pe" dimensions during request processing. When used as
* dimension/filter values (e.g., "ENROLLMENT_DATE:2021"), they represent period constraints and
* should prevent a default period from being added.
*/
private static final Set<String> STATIC_DATE_DIMENSIONS =
Set.of("ENROLLMENT_DATE", "INCIDENT_DATE", "LAST_UPDATED", "CREATED_DATE", "COMPLETED_DATE");

private static boolean hasStaticDateDimension(Set<String> dims) {
return dims.stream()
.anyMatch(d -> STATIC_DATE_DIMENSIONS.stream().anyMatch(sd -> d.startsWith(sd + ":")));
}

/**
* Add a default period for the given criteria, if none is present.
*
Expand Down Expand Up @@ -83,6 +97,8 @@ public static boolean hasPeriod(EventsAnalyticsQueryCriteria criteria) {
|| criteria.getFilter().stream().anyMatch(d -> d.contains(".EVENT_DATE:"))
|| criteria.getDimension().stream().anyMatch(d -> d.contains(".SCHEDULED_DATE:"))
|| criteria.getFilter().stream().anyMatch(d -> d.contains(".SCHEDULED_DATE:"))
|| hasStaticDateDimension(criteria.getDimension())
|| hasStaticDateDimension(criteria.getFilter())
|| !isBlank(criteria.getEventDate())
|| !isBlank(criteria.getOccurredDate())
|| !isBlank(criteria.getEnrollmentDate())
Expand All @@ -106,6 +122,8 @@ public static boolean hasPeriod(EventsAnalyticsQueryCriteria criteria) {
public static boolean hasPeriod(EnrollmentAnalyticsQueryCriteria criteria) {
return criteria.getDimension().stream().anyMatch(d -> d.startsWith(PERIOD_DIM_ID))
|| (criteria.getFilter().stream().anyMatch(d -> d.startsWith(PERIOD_DIM_ID)))
|| hasStaticDateDimension(criteria.getDimension())
|| hasStaticDateDimension(criteria.getFilter())
|| !isBlank(criteria.getEnrollmentDate())
|| (criteria.getStartDate() != null && criteria.getEndDate() != null)
|| !isBlank(criteria.getIncidentDate())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,43 @@ void testHasPeriodEnrollment_false_whenNoPeriodInformationPresent() {
assertFalse(PeriodCriteriaUtils.hasPeriod(c));
}

@Test
void testHasPeriodEvent_whenDimensionContainsEnrollmentDate() {
EventsAnalyticsQueryCriteria c = getDefaultEventsAnalyticsQueryCriteria();
c.getDimension().add("ENROLLMENT_DATE:2021");
assertTrue(PeriodCriteriaUtils.hasPeriod(c));
}

@Test
void testHasPeriodEvent_whenDimensionContainsIncidentDate() {
EventsAnalyticsQueryCriteria c = getDefaultEventsAnalyticsQueryCriteria();
c.getDimension().add("INCIDENT_DATE:THIS_YEAR");
assertTrue(PeriodCriteriaUtils.hasPeriod(c));
}

@Test
void testHasPeriodEvent_whenFilterContainsEnrollmentDate() {
EventsAnalyticsQueryCriteria c = getDefaultEventsAnalyticsQueryCriteria();
Set<String> filters = new HashSet<>();
filters.add("ENROLLMENT_DATE:2021");
c.setFilter(filters);
assertTrue(PeriodCriteriaUtils.hasPeriod(c));
}

@Test
void testHasPeriodEnrollment_whenDimensionContainsEnrollmentDateDim() {
EnrollmentAnalyticsQueryCriteria c = getDefaultEnrollmentsAnalyticsQueryCriteria();
c.getDimension().add("ENROLLMENT_DATE:2021");
assertTrue(PeriodCriteriaUtils.hasPeriod(c));
}

@Test
void testHasPeriodEnrollment_whenDimensionContainsIncidentDateDim() {
EnrollmentAnalyticsQueryCriteria c = getDefaultEnrollmentsAnalyticsQueryCriteria();
c.getDimension().add("INCIDENT_DATE:LAST_12_MONTHS");
assertTrue(PeriodCriteriaUtils.hasPeriod(c));
}

@Test
void testHasPeriodEvent_whenDimensionContainsStageDotEventDate() {
EventsAnalyticsQueryCriteria c = getDefaultEventsAnalyticsQueryCriteria();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,18 @@ public class EventQueryParams extends DataQueryParams {

@Getter protected List<OrganisationUnit> userOrgUnits = new ArrayList<>();

/** Items when ENROLLMENT_OU is used as a dimension. */
private List<DimensionalItemObject> enrollmentOuDimensionItems = new ArrayList<>();

/** Items when ENROLLMENT_OU is used as a filter. */
private List<DimensionalItemObject> enrollmentOuFilterItems = new ArrayList<>();

/** Level constraints when ENROLLMENT_OU is used as a dimension. */
private Set<Integer> enrollmentOuDimensionLevels = new LinkedHashSet<>();

/** Level constraints when ENROLLMENT_OU is used as a filter. */
private Set<Integer> enrollmentOuFilterLevels = new LinkedHashSet<>();

// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
Expand Down Expand Up @@ -341,6 +353,10 @@ protected EventQueryParams instance() {
params.userOrgUnits = this.userOrgUnits;
params.outputFormat = this.outputFormat;
params.piDisagInfo = this.piDisagInfo;
params.enrollmentOuDimensionItems = new ArrayList<>(this.enrollmentOuDimensionItems);
params.enrollmentOuFilterItems = new ArrayList<>(this.enrollmentOuFilterItems);
params.enrollmentOuDimensionLevels = new LinkedHashSet<>(this.enrollmentOuDimensionLevels);
params.enrollmentOuFilterLevels = new LinkedHashSet<>(this.enrollmentOuFilterLevels);
return params;
}

Expand Down Expand Up @@ -1249,6 +1265,53 @@ public boolean hasDataIdScheme() {
return dataIdScheme != null;
}

public boolean hasEnrollmentOuDimension() {
return isNotEmpty(enrollmentOuDimensionItems) || !enrollmentOuDimensionLevels.isEmpty();
}

public boolean hasEnrollmentOuFilter() {
return isNotEmpty(enrollmentOuFilterItems) || !enrollmentOuFilterLevels.isEmpty();
}

public boolean hasEnrollmentOu() {
return hasEnrollmentOuDimension() || hasEnrollmentOuFilter();
}

public List<DimensionalItemObject> getEnrollmentOuDimensionItems() {
return enrollmentOuDimensionItems;
}

public List<DimensionalItemObject> getEnrollmentOuFilterItems() {
return enrollmentOuFilterItems;
}

/** Returns all enrollment OU items from both dimension and filter. */
public List<DimensionalItemObject> getAllEnrollmentOuItems() {
return ListUtils.union(enrollmentOuDimensionItems, enrollmentOuFilterItems);
}

public Set<Integer> getEnrollmentOuDimensionLevels() {
return enrollmentOuDimensionLevels;
}

public Set<Integer> getEnrollmentOuFilterLevels() {
return enrollmentOuFilterLevels;
}

public boolean hasEnrollmentOuLevelConstraint() {
return !enrollmentOuDimensionLevels.isEmpty() || !enrollmentOuFilterLevels.isEmpty();
}

public Set<Integer> getAllEnrollmentOuLevelsForSql() {
Set<Integer> levels = new LinkedHashSet<>(enrollmentOuDimensionLevels);
levels.addAll(enrollmentOuFilterLevels);
return levels;
}

public List<DimensionalItemObject> getAllEnrollmentOuItemsForSql() {
return getAllEnrollmentOuItems();
}

/**
* Returns a negative integer in case of ascending sort order, a positive in case of descending
* sort order and 0 in case of no sort order.
Expand Down Expand Up @@ -1802,6 +1865,26 @@ public Builder withPiDisagInfo(PiDisagInfo piDisagInfo) {
return this;
}

public Builder withEnrollmentOuDimension(List<DimensionalItemObject> items) {
this.params.enrollmentOuDimensionItems = items;
return this;
}

public Builder withEnrollmentOuFilter(List<DimensionalItemObject> items) {
this.params.enrollmentOuFilterItems = items;
return this;
}

public Builder withEnrollmentOuDimensionLevels(Set<Integer> levels) {
this.params.enrollmentOuDimensionLevels = new LinkedHashSet<>(levels);
return this;
}

public Builder withEnrollmentOuFilterLevels(Set<Integer> levels) {
this.params.enrollmentOuFilterLevels = new LinkedHashSet<>(levels);
return this;
}

public void addMeasureCriteria(MeasureFilter filter, Double value) {
this.params.measureCriteria.put(filter, value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
import org.hisp.dhis.analytics.common.InQueryCteFilter;
import org.hisp.dhis.analytics.common.ProgramIndicatorSubqueryBuilder;
import org.hisp.dhis.analytics.event.EventQueryParams;
import org.hisp.dhis.analytics.event.data.ou.OrgUnitSqlCoordinator;
import org.hisp.dhis.analytics.event.data.programindicator.disag.PiDisagDataHandler;
import org.hisp.dhis.analytics.event.data.programindicator.disag.PiDisagInfoInitializer;
import org.hisp.dhis.analytics.event.data.programindicator.disag.PiDisagQueryGenerator;
Expand Down Expand Up @@ -513,7 +514,7 @@ private List<String> getSelectColumns(
EventQueryParams params, boolean isGroupByClause, boolean isAggregated) {
List<String> columns = new ArrayList<>();

addDimensionSelectColumns(columns, params, isGroupByClause);
addDimensionSelectColumns(columns, params, isGroupByClause, isAggregated);
addItemSelectColumns(columns, params, isGroupByClause, isAggregated);

return columns;
Expand All @@ -530,7 +531,10 @@ private List<String> getSelectColumns(
* group by columns.
*/
protected void addDimensionSelectColumns(
List<String> columns, EventQueryParams params, boolean isGroupByClause) {
List<String> columns,
EventQueryParams params,
boolean isGroupByClause,
boolean isAggregated) {
params
.getDimensions()
.forEach(
Expand Down Expand Up @@ -588,6 +592,9 @@ protected void addDimensionSelectColumns(
exactly one period, or no periods and a period filter""");
}
});

OrgUnitSqlCoordinator.addDimensionSelectColumns(
columns, params, isGroupByClause, isAggregated, getAnalyticsType());
}

private void addItemSelectColumns(
Expand Down Expand Up @@ -1802,7 +1809,7 @@ protected List<String> getSelectColumnsWithCTE(EventQueryParams params, CteConte
// Add dimension columns only when the analytics query
// is for enrollments
if (!cteContext.isEventsAnalytics()) {
addDimensionSelectColumns(columns, params, false);
addDimensionSelectColumns(columns, params, false, false);
}

// Process query items with CTE references
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.function.BiFunction;
import java.util.function.Function;
import org.hisp.dhis.analytics.event.EventQueryParams;
import org.hisp.dhis.analytics.event.data.ou.OrgUnitRowAccess;
import org.hisp.dhis.common.DimensionalObject;
import org.hisp.dhis.common.IdScheme;
import org.hisp.dhis.common.QueryItem;
Expand Down Expand Up @@ -193,6 +194,10 @@ private void addDimensionData() {
extractStringValue(dimension.getDimensionName(), dimension.getValueType());
row.add(dimensionValue);
}

if (params.hasEnrollmentOuDimension()) {
row.add(extractStringValue(OrgUnitRowAccess.enrollmentOuResultColumn(), ValueType.TEXT));
}
}

/**
Expand Down
Loading