From 81c224939ee3e56907d29892ca8e79f1a6d4d12e Mon Sep 17 00:00:00 2001 From: Maikel Arabori <51713408+maikelarabori@users.noreply.github.com> Date: Fri, 24 May 2024 10:01:25 +0200 Subject: [PATCH] fix: ValueType in metadata [DHIS2-15194] (#17548) (#17559) * fix: ValueType in metadata [DHIS2-15194] * fix: Code formatting [DHIS2-15194] --- .../org/hisp/dhis/common/MetadataItem.java | 50 ++++++++---- .../aggregate/AnalyticsQueryTest.java | 77 +++++++++++++++++++ 2 files changed, 111 insertions(+), 16 deletions(-) diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MetadataItem.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MetadataItem.java index bc40445a8ce4..ca09ff84f288 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MetadataItem.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/MetadataItem.java @@ -29,6 +29,7 @@ import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.apache.commons.lang3.StringUtils.appendIfMissing; +import static org.hisp.dhis.common.ValueType.NUMBER; import static org.hisp.dhis.common.ValueType.TEXT; import com.fasterxml.jackson.annotation.JsonProperty; @@ -58,6 +59,7 @@ import org.hisp.dhis.program.ProgramDataElementDimensionItem; import org.hisp.dhis.program.ProgramIndicator; import org.hisp.dhis.program.ProgramStage; +import org.hisp.dhis.program.ProgramTrackedEntityAttributeDimensionItem; import org.hisp.dhis.trackedentity.TrackedEntityAttribute; /** @@ -206,7 +208,7 @@ private void setDataItem(DimensionalItemObject dimensionalItemObject) { this.code = dimensionalItemObject.getCode(); this.description = dimensionalItemObject.getDescription(); this.dimensionItemType = dimensionalItemObject.getDimensionItemType(); - this.valueType = ValueType.NUMBER; // Default value + this.valueType = getValueType(dimensionalItemObject); this.aggregationType = dimensionalItemObject.getAggregationType(); this.totalAggregationType = dimensionalItemObject.getTotalAggregationType(); @@ -216,30 +218,46 @@ private void setDataItem(DimensionalItemObject dimensionalItemObject) { // TODO common interface - if (dimensionalItemObject instanceof DataElement dataElement) { - this.valueType = dataElement.getValueType().toSimplifiedValueType(); - } else if (dimensionalItemObject instanceof DataElementOperand operand) { - this.valueType = operand.getValueType().toSimplifiedValueType(); - } else if (dimensionalItemObject instanceof TrackedEntityAttribute attribute) { - this.valueType = attribute.getValueType().toSimplifiedValueType(); - } else if (dimensionalItemObject instanceof Period period) { + if (dimensionalItemObject instanceof Period period) { this.startDate = period.getStartDate(); this.endDate = period.getEndDate(); - this.valueType = TEXT; - } else if (dimensionalItemObject instanceof Indicator indicator) { - if (indicator.getIndicatorType() != null) { - this.indicatorType = HibernateProxyUtils.unproxy(indicator.getIndicatorType()); - } + } else if (dimensionalItemObject instanceof Indicator indicator + && indicator.getIndicatorType() != null) { + this.indicatorType = HibernateProxyUtils.unproxy(indicator.getIndicatorType()); } else if (dimensionalItemObject instanceof ExpressionDimensionItem expressionDimensionItem) { this.expression = expressionDimensionItem.getExpression(); + } + + addIconPathToStyle(getDimensionalItemObjectStyle(dimensionalItemObject)); + } + + /** + * Gets the {@link ValueType} related to the instance of the given {@link DimensionalItemObject}. + * If there is no match, {@link NUMBER} is returned as default. + * + * @param dimensionalItemObject the {@link DimensionalItemObject}. + * @return the respective {@link ValueType}. + */ + private ValueType getValueType(DimensionalItemObject dimensionalItemObject) { + if (dimensionalItemObject instanceof DataElement dataElement) { + return dataElement.getValueType().toSimplifiedValueType(); + } else if (dimensionalItemObject instanceof DataElementOperand operand) { + return operand.getValueType().toSimplifiedValueType(); + } else if (dimensionalItemObject instanceof TrackedEntityAttribute attribute) { + return attribute.getValueType().toSimplifiedValueType(); + } else if (dimensionalItemObject instanceof Period) { + return TEXT; } else if (dimensionalItemObject instanceof ProgramDataElementDimensionItem programDataElementDimensionItem) { - this.valueType = programDataElementDimensionItem.getValueType(); + return programDataElementDimensionItem.getValueType(); } else if (dimensionalItemObject instanceof OrganisationUnit) { - this.valueType = TEXT; + return TEXT; + } else if (dimensionalItemObject instanceof ProgramTrackedEntityAttributeDimensionItem item + && item.getAttribute() != null) { + return item.getAttribute().getValueType().toSimplifiedValueType(); } - addIconPathToStyle(getDimensionalItemObjectStyle(dimensionalItemObject)); + return NUMBER; } /** diff --git a/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/analytics/aggregate/AnalyticsQueryTest.java b/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/analytics/aggregate/AnalyticsQueryTest.java index 476fc43d6849..ce98a5348b54 100644 --- a/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/analytics/aggregate/AnalyticsQueryTest.java +++ b/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/analytics/aggregate/AnalyticsQueryTest.java @@ -34,12 +34,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; +import java.util.Map; import org.hisp.dhis.AnalyticsApiTest; import org.hisp.dhis.actions.RestApiActions; import org.hisp.dhis.dto.ApiResponse; import org.hisp.dhis.helpers.QueryParamsBuilder; +import org.json.JSONException; +import org.json.JSONObject; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.skyscreamer.jsonassert.JSONAssert; /** * Groups e2e tests for "/analytics" endpoint. @@ -47,6 +51,7 @@ * @author dusan bernat */ public class AnalyticsQueryTest extends AnalyticsApiTest { + private RestApiActions analyticsActions; @BeforeAll @@ -459,4 +464,76 @@ public void testQueryForReportingRatesWithMeasureCriteriaEQ_WithZerosAsResult() validateRow(response, List.of("PLq9sJluXvc.REPORTING_RATE", "2023", "PMa2VCrupOd", "0")); } + + @Test + public void queryProgramTrackedEntityAttributeDimensionItemValueType() throws JSONException { + // Given + QueryParamsBuilder params = + new QueryParamsBuilder() + .add("filter=ou:USER_ORGUNIT") + .add("skipData=false") + .add("includeNumDen=true") + .add("displayProperty=NAME") + .add("skipMeta=false") + .add("dimension=dx:IpHINAT79UW.w75KJ2mc4zz,pe:LAST_YEAR") + .add("relativePeriodDate=2024-05-22"); + + // When + ApiResponse response = analyticsActions.get(params); + + // Then + response + .validate() + .statusCode(200) + .body("headers", hasSize(equalTo(8))) + .body("rows", hasSize(equalTo(19))) + .body("height", equalTo(19)) + .body("width", equalTo(8)) + .body("headerWidth", equalTo(8)); + + // Assert metaData. + String expectedMetaData = + "{\"items\":{\"ImspTQPwCqd\":{\"name\":\"Sierra Leone\"},\"dx\":{\"name\":\"Data\"},\"pe\":{\"name\":\"Period\"},\"ou\":{\"name\":\"Organisation unit\"},\"2023\":{\"name\":\"2023\"},\"LAST_YEAR\":{\"name\":\"Last year\"},\"IpHINAT79UW.w75KJ2mc4zz\":{\"name\":\"Child Programme First name\"}},\"dimensions\":{\"dx\":[\"IpHINAT79UW.w75KJ2mc4zz\"],\"pe\":[\"2023\"],\"ou\":[\"ImspTQPwCqd\"],\"co\":[]}}"; + String actualMetaData = new JSONObject((Map) response.extract("metaData")).toString(); + JSONAssert.assertEquals(expectedMetaData, actualMetaData, false); + + // Assert headers. + validateHeader(response, 0, "dx", "Data", "TEXT", "java.lang.String", false, true); + validateHeader(response, 1, "pe", "Period", "TEXT", "java.lang.String", false, true); + validateHeader(response, 2, "value", "Value", "NUMBER", "java.lang.Double", false, false); + validateHeader( + response, 3, "numerator", "Numerator", "NUMBER", "java.lang.Double", false, false); + validateHeader( + response, 4, "denominator", "Denominator", "NUMBER", "java.lang.Double", false, false); + validateHeader(response, 5, "factor", "Factor", "NUMBER", "java.lang.Double", false, false); + validateHeader( + response, 6, "multiplier", "Multiplier", "NUMBER", "java.lang.Double", false, false); + validateHeader(response, 7, "divisor", "Divisor", "NUMBER", "java.lang.Double", false, false); + + // Assert rows. + validateRow( + response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Antonio", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Jane", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Jane", "", "", "", "", "")); + validateRow( + response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Jonathan", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Walter", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Helen", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Andrea", "", "", "", "", "")); + validateRow( + response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Matthew", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Tammy", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Joan", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Scott", "", "", "", "", "")); + validateRow( + response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Patricia", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Sandra", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Maria", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Aaron", "", "", "", "", "")); + validateRow( + response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Catherine", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Evelyn", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Ruth", "", "", "", "", "")); + validateRow(response, List.of("IpHINAT79UW.w75KJ2mc4zz", "2023", "Gary", "", "", "", "", "")); + } }