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: adds ou to meta when DE ou [DHIS2-18884] #19764

Merged
merged 11 commits into from
Jan 27, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
package org.hisp.dhis.util;

import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
import static org.hisp.dhis.analytics.AnalyticsMetaDataKey.USER_ORGUNIT;
import static org.hisp.dhis.analytics.AnalyticsMetaDataKey.USER_ORGUNIT_CHILDREN;
import static org.hisp.dhis.analytics.AnalyticsMetaDataKey.USER_ORGUNIT_GRANDCHILDREN;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
Expand All @@ -54,22 +56,22 @@ public static List<AnalyticsMetaDataKey> getAnalyticsMetaDataKeys(
String userOrganisationUnitsCriteria) {
List<AnalyticsMetaDataKey> keys = new ArrayList<>();

if (userOrganisationUnitsCriteria == null
|| !userOrganisationUnitsCriteria.contains(ORGUNIT_DIM_ID + ":")) {
return keys;
// order matters, don't change unless you know what you're doing
gnespolino marked this conversation as resolved.
Show resolved Hide resolved
AnalyticsMetaDataKey[] analyticsMetaDataKeys = {
USER_ORGUNIT_CHILDREN, USER_ORGUNIT_GRANDCHILDREN, USER_ORGUNIT
};
for (AnalyticsMetaDataKey key : analyticsMetaDataKeys) {
if (StringUtils.trimToEmpty(userOrganisationUnitsCriteria).contains(key.getKey())) {
keys.add(key);
// we need this hack, and the analyticsMetaDataKeys order, because otherwise it would match
gnespolino marked this conversation as resolved.
Show resolved Hide resolved
// USER_ORGUNIT_CHILDREN even if we only get USER_ORGUNIT, since the latter contains the
// former
gnespolino marked this conversation as resolved.
Show resolved Hide resolved
userOrganisationUnitsCriteria =
userOrganisationUnitsCriteria.replace(key.getKey(), StringUtils.EMPTY);
}
}

userOrganisationUnitsCriteria =
userOrganisationUnitsCriteria.replace(ORGUNIT_DIM_ID + ":", StringUtils.EMPTY);
List<String> criteria = Arrays.stream(userOrganisationUnitsCriteria.split(";")).toList();
return criteria.stream()
.filter(
c ->
c.equalsIgnoreCase(AnalyticsMetaDataKey.USER_ORGUNIT.getKey())
|| c.equalsIgnoreCase(AnalyticsMetaDataKey.USER_ORGUNIT_CHILDREN.getKey())
|| c.equalsIgnoreCase(AnalyticsMetaDataKey.USER_ORGUNIT_GRANDCHILDREN.getKey()))
.map(AnalyticsMetaDataKey::valueOf)
.toList();
return keys;
}

/**
Expand All @@ -82,8 +84,16 @@ public static List<AnalyticsMetaDataKey> getAnalyticsMetaDataKeys(
public static String getAnalyticsQueryCriteria(Set<String> dimensions) {
return isNotEmpty(dimensions)
? dimensions.stream()
.filter(d -> d.contains(ORGUNIT_DIM_ID))
.filter(OrganisationUnitCriteriaUtils::containsAnyUserOrgUnitKeyword)
.collect(Collectors.joining(","))
: StringUtils.EMPTY;
}

private static boolean containsAnyUserOrgUnitKeyword(String dimension) {
return Stream.of(
USER_ORGUNIT.getKey(),
AnalyticsMetaDataKey.USER_ORGUNIT_CHILDREN.getKey(),
AnalyticsMetaDataKey.USER_ORGUNIT_GRANDCHILDREN.getKey())
.anyMatch(dimension::contains);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
*/
package org.hisp.dhis.util;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItems;
import static org.hisp.dhis.analytics.AnalyticsMetaDataKey.USER_ORGUNIT;
import static org.hisp.dhis.analytics.AnalyticsMetaDataKey.USER_ORGUNIT_CHILDREN;
import static org.hisp.dhis.analytics.AnalyticsMetaDataKey.USER_ORGUNIT_GRANDCHILDREN;
Expand All @@ -36,7 +38,6 @@

import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.hisp.dhis.analytics.AnalyticsMetaDataKey;
import org.hisp.dhis.common.AggregateAnalyticsQueryCriteria;
import org.hisp.dhis.common.EnrollmentAnalyticsQueryCriteria;
Expand All @@ -46,8 +47,6 @@
class OrganisationUnitCriteriaUtilsTest {
private static final String validOuDimensions =
"ou:USER_ORGUNIT;USER_ORGUNIT_CHILDREN;USER_ORGUNIT_GRANDCHILDREN";
private static final String invalidOuDimensions =
"USER_ORGUNIT;USER_ORGUNIT_CHILDREN;USER_ORGUNIT_GRANDCHILDREN";

@Test
void testGetAnalyticsMetaDataKeys_All() {
Expand All @@ -56,19 +55,7 @@ void testGetAnalyticsMetaDataKeys_All() {
List<AnalyticsMetaDataKey> keys = getAnalyticsMetaDataKeys(validOuDimensions);
// then
assertEquals(3, keys.size());
assertEquals(USER_ORGUNIT.getKey(), keys.get(0).getKey());
assertEquals(USER_ORGUNIT_CHILDREN.getKey(), keys.get(1).getKey());
assertEquals(USER_ORGUNIT_GRANDCHILDREN.getKey(), keys.get(2).getKey());
}

@Test
void testGetAnalyticsMetaDataKeys_Unsupported() {
// given
// when
List<AnalyticsMetaDataKey> keys = getAnalyticsMetaDataKeys(invalidOuDimensions);

// then
assertEquals(0, keys.size());
assertThat(keys, hasItems(USER_ORGUNIT, USER_ORGUNIT_CHILDREN, USER_ORGUNIT_GRANDCHILDREN));
}

@Test
Expand Down Expand Up @@ -114,48 +101,4 @@ void testGetAnalyticsQueryCriteria_Aggregate() {
// then
assertEquals(validOuDimensions, analyticsQueryCriteria);
}

maikelarabori marked this conversation as resolved.
Show resolved Hide resolved
@Test
void testGetAnalyticsQueryCriteria_Enrollment_No_Dimension() {
// given
EnrollmentAnalyticsQueryCriteria enrollmentAnalyticsQueryCriteria =
new EnrollmentAnalyticsQueryCriteria();
enrollmentAnalyticsQueryCriteria.setDimension(Set.of(invalidOuDimensions));

// when
String analyticsQueryCriteria =
getAnalyticsQueryCriteria(enrollmentAnalyticsQueryCriteria.getDimension());

// then
assertEquals(StringUtils.EMPTY, analyticsQueryCriteria);
}

@Test
void testGetAnalyticsQueryCriteria_Event_No_Dimension() {
// given
EventsAnalyticsQueryCriteria eventsAnalyticsQueryCriteria = new EventsAnalyticsQueryCriteria();
eventsAnalyticsQueryCriteria.setDimension(Set.of(invalidOuDimensions));

// when
String analyticsQueryCriteria =
getAnalyticsQueryCriteria(eventsAnalyticsQueryCriteria.getDimension());

// then
assertEquals(StringUtils.EMPTY, analyticsQueryCriteria);
}

@Test
void testGetAnalyticsQueryCriteria_Aggregate_No_Dimension() {
// given
AggregateAnalyticsQueryCriteria aggregateAnalyticsQueryCriteria =
new AggregateAnalyticsQueryCriteria();
aggregateAnalyticsQueryCriteria.setDimension(Set.of(invalidOuDimensions));

// when
String analyticsQueryCriteria =
getAnalyticsQueryCriteria(aggregateAnalyticsQueryCriteria.getDimension());

// then
assertEquals(StringUtils.EMPTY, analyticsQueryCriteria);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ public class EventQueryParams extends DataQueryParams {

@Getter protected boolean multipleQueries = false;

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

// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
Expand Down Expand Up @@ -305,6 +307,7 @@ protected EventQueryParams instance() {
params.rowContext = this.rowContext;
params.multipleQueries = this.multipleQueries;
params.userOrganisationUnitsCriteria = this.userOrganisationUnitsCriteria;
params.userOrgUnits = this.userOrgUnits;
return params;
}

Expand Down Expand Up @@ -1360,5 +1363,10 @@ public Builder withMultipleQueries(boolean multipleQueries) {
this.params.multipleQueries = multipleQueries;
return this;
}

public Builder withUserOrgUnits(List<OrganisationUnit> userOrgUnits) {
this.params.userOrgUnits = userOrgUnits;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ public abstract class AbstractJdbcEventAnalyticsManager {

private final DhisConfigurationProvider config;

private final OrganisationUnitResolver organisationUnitResolver;

/**
* Returns a SQL paging clause.
*
Expand Down Expand Up @@ -1277,9 +1279,14 @@ public String toSql(QueryItem item, QueryFilter filter, EventQueryParams params)
? getSelectSql(filter, item, params)
: getSelectSql(filter, item, params.getEarliestStartDate(), params.getLatestEndDate());

String filterString =
item.getValueType().isOrganisationUnit()
? organisationUnitResolver.resolveOrgUnits(filter, params.getUserOrgUnits())
: filter.getFilter();

if (IN.equals(filter.getOperator())) {
InQueryFilter inQueryFilter =
new InQueryFilter(field, sqlBuilder.escape(filter.getFilter()), !item.isNumeric());
new InQueryFilter(field, sqlBuilder.escape(filterString), !item.isNumeric());

return inQueryFilter.getSqlFilter();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,13 @@
import static org.hisp.dhis.analytics.util.AnalyticsUtils.illegalQueryExSupplier;
import static org.hisp.dhis.analytics.util.AnalyticsUtils.throwIllegalQueryEx;
import static org.hisp.dhis.common.DimensionalObject.DIMENSION_NAME_SEP;
import static org.hisp.dhis.common.DimensionalObject.OPTION_SEP;
import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionFromParam;
import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionItemsFromParam;
import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensionalItemIds;
import static org.hisp.dhis.common.ValueType.ORGANISATION_UNIT;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
Expand All @@ -57,7 +54,6 @@
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.hisp.dhis.analytics.AnalyticsAggregationType;
import org.hisp.dhis.analytics.DataQueryParams;
Expand Down Expand Up @@ -206,7 +202,8 @@ public EventQueryParams getFromRequest(EventDataQueryRequest request, boolean an
.withEndpointItem(request.getEndpointItem())
.withEndpointAction(request.getEndpointAction())
.withUserOrganisationUnitsCriteria(request.getUserOrganisationUnitCriteria())
.withRowContext(request.isRowContext());
.withRowContext(request.isRowContext())
.withUserOrgUnits(userOrgUnits);

if (analyzeOnly) {
builder = builder.withSkipData(true).withAnalyzeOrderId();
Expand Down Expand Up @@ -322,7 +319,7 @@ private void addDimensionsToParams(
if (groupableItem != null) {
params.addDimension((DimensionalObject) groupableItem);
} else {
groupableItem = getQueryItem(dim, pr, request.getOutputType(), userOrgUnits);
groupableItem = getQueryItem(dim, pr, request.getOutputType());
params.addItem((QueryItem) groupableItem);
}

Expand Down Expand Up @@ -515,14 +512,6 @@ private QueryItem getQueryItem(

@Override
public QueryItem getQueryItem(String dimensionString, Program program, EventOutputType type) {
return getQueryItem(dimensionString, program, type, Collections.emptyList());
}

private QueryItem getQueryItem(
String dimensionString,
Program program,
EventOutputType type,
List<OrganisationUnit> userOrgUnits) {
String[] split = dimensionString.split(DIMENSION_NAME_SEP);

if (split.length % 2 != 1) {
Expand All @@ -548,25 +537,13 @@ private QueryItem getQueryItem(
// FE uses HH.MM time format instead of HH:MM. This is not
// compatible with db table/cell values
modifyFilterWhenTimeQueryItem(queryItem, filter);
resolveOrgUnitDimensionIfNecessary(queryItem, filter, userOrgUnits);
queryItem.addFilter(filter);
}
}

return queryItem;
}

@SneakyThrows
private void resolveOrgUnitDimensionIfNecessary(
QueryItem queryItem, QueryFilter queryFilter, List<OrganisationUnit> userOrgUnits) {
if (queryItem.getValueType().equals(ORGANISATION_UNIT)) {
List<String> filterItem = QueryFilter.getFilterItems(queryFilter.getFilter());
List<String> orgUnitDimensionUid =
dataQueryService.getOrgUnitDimensionUid(filterItem, userOrgUnits);
queryFilter.setFilter(String.join(OPTION_SEP, orgUnitDimensionUid));
}
}

private static void modifyFilterWhenTimeQueryItem(QueryItem queryItem, QueryFilter filter) {
if (queryItem.getItem() instanceof DataElement
&& ((DataElement) queryItem.getItem()).getValueType() == ValueType.TIME) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,17 @@ public JdbcEnrollmentAnalyticsManager(
ExecutionPlanStore executionPlanStore,
SystemSettingsService settingsService,
DhisConfigurationProvider config,
SqlBuilder sqlBuilder) {
SqlBuilder sqlBuilder,
OrganisationUnitResolver organisationUnitResolver) {
super(
jdbcTemplate,
programIndicatorService,
programIndicatorSubqueryBuilder,
executionPlanStore,
sqlBuilder,
settingsService,
config);
config,
organisationUnitResolver);
this.timeFieldSqlRenderer = timeFieldSqlRenderer;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,17 @@ public JdbcEventAnalyticsManager(
ExecutionPlanStore executionPlanStore,
SystemSettingsService settingsService,
DhisConfigurationProvider config,
SqlBuilder sqlBuilder) {
SqlBuilder sqlBuilder,
OrganisationUnitResolver organisationUnitResolver) {
super(
jdbcTemplate,
programIndicatorService,
programIndicatorSubqueryBuilder,
executionPlanStore,
sqlBuilder,
settingsService,
config);
config,
organisationUnitResolver);
this.timeFieldSqlRenderer = timeFieldSqlRenderer;
}

Expand Down
Loading
Loading