From 14ee171df2caca07272f6f1ef19e73388ac033c6 Mon Sep 17 00:00:00 2001 From: Jason Pickering Date: Thu, 19 Feb 2026 17:42:38 +0100 Subject: [PATCH] Refactor ADEX orgunits to use UIDs --- .../dataexchange/aggregate/SourceRequest.java | 3 ++- .../aggregate/AggregateDataExchangeService.java | 8 ++++++-- .../AggregateDataExchangeServiceTest.java | 3 ++- .../main/java/org/hisp/dhis/test/TestBase.java | 3 ++- .../MetadataImportExportControllerTest.java | 15 +++++++++++++++ .../webapi/controller/CrudControllerAdvice.java | 2 ++ 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataexchange/aggregate/SourceRequest.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataexchange/aggregate/SourceRequest.java index dd98fe50c442..33bec509670d 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataexchange/aggregate/SourceRequest.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataexchange/aggregate/SourceRequest.java @@ -38,6 +38,7 @@ import lombok.Setter; import lombok.experimental.Accessors; import org.hisp.dhis.analytics.AggregationType; +import org.hisp.dhis.common.UID; @Getter @Setter @@ -57,7 +58,7 @@ public class SourceRequest implements Serializable { @JsonProperty private List pe = new ArrayList<>(); /** Org unit identifiers. */ - @JsonProperty private List ou = new ArrayList<>(); + @JsonProperty private List ou = new ArrayList<>(); /** Request filters. */ @JsonProperty private List filters = new ArrayList<>(); diff --git a/dhis-2/dhis-services/dhis-service-data-exchange/src/main/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeService.java b/dhis-2/dhis-services/dhis-service-data-exchange/src/main/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeService.java index 7d2bb9604762..bbcef5b8a90e 100644 --- a/dhis-2/dhis-services/dhis-service-data-exchange/src/main/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeService.java +++ b/dhis-2/dhis-services/dhis-service-data-exchange/src/main/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeService.java @@ -55,6 +55,7 @@ import org.hisp.dhis.common.Grid; import org.hisp.dhis.common.IdScheme; import org.hisp.dhis.common.IllegalQueryException; +import org.hisp.dhis.common.UID; import org.hisp.dhis.dataexchange.client.Dhis2Client; import org.hisp.dhis.datavalue.DataEntryGroup; import org.hisp.dhis.datavalue.DataEntryPipeline; @@ -361,7 +362,8 @@ DataQueryParams toDataQueryParams(SourceRequest request, SourceDataQueryParams p return DataQueryParams.newBuilder() .addDimension(toDimensionalObject(DATA_X_DIM_ID, request.getDx(), inputIdScheme)) .addDimension(toDimensionalObject(PERIOD_DIM_ID, request.getPe(), inputIdScheme)) - .addDimension(toDimensionalObject(ORGUNIT_DIM_ID, request.getOu(), inputIdScheme)) + .addDimension( + toDimensionalObject(ORGUNIT_DIM_ID, UID.toValueList(request.getOu()), inputIdScheme)) .addFilters(filters) .withAggregationType(toAnalyticsAggregationType(request.getAggregationType())) .withOutputDataElementIdScheme(outputDataElementIdScheme) @@ -500,7 +502,9 @@ private static String toStageDescription(AggregateDataExchange exchange) { private static String toItemDescription(SourceRequest request) { return format( "dx: %s; pe: %s; ou: %s", - join(",", request.getDx()), join(",", request.getPe()), join(",", request.getOu())); + join(",", request.getDx()), + join(",", request.getPe()), + join(",", UID.toValueList(request.getOu()))); } /** diff --git a/dhis-2/dhis-services/dhis-service-data-exchange/src/test/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeServiceTest.java b/dhis-2/dhis-services/dhis-service-data-exchange/src/test/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeServiceTest.java index b4c6f04efd40..864115ca17f8 100644 --- a/dhis-2/dhis-services/dhis-service-data-exchange/src/test/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeServiceTest.java +++ b/dhis-2/dhis-services/dhis-service-data-exchange/src/test/java/org/hisp/dhis/dataexchange/aggregate/AggregateDataExchangeServiceTest.java @@ -56,6 +56,7 @@ import org.hisp.dhis.common.DisplayProperty; import org.hisp.dhis.common.IdScheme; import org.hisp.dhis.common.IdentifiableObject; +import org.hisp.dhis.common.UID; import org.hisp.dhis.dataexchange.client.Dhis2Client; import org.hisp.dhis.datavalue.DataExportService; import org.hisp.dhis.dxf2.common.ImportOptions; @@ -121,7 +122,7 @@ void testToDataQueryParams() { .setName("SourceRequestA") .setDx(List.of("Vz0C3i4Wy3M", "ToaOToReol6")) .setPe(List.of("202101", "202102")) - .setOu(List.of("lGgJFgRkZui", "pvINfKxtqyN", "VOyqQ54TehY")) + .setOu(List.of(UID.of("lGgJFgRkZui"), UID.of("pvINfKxtqyN"), UID.of("VOyqQ54TehY"))) .setAggregationType(AggregationType.COUNT) .setOutputDataElementIdScheme(IdScheme.UID.name()) .setOutputOrgUnitIdScheme(IdScheme.CODE.name()) diff --git a/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/TestBase.java b/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/TestBase.java index 26061148d96c..83dde74ad7f5 100644 --- a/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/TestBase.java +++ b/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/TestBase.java @@ -89,6 +89,7 @@ import org.hisp.dhis.common.IllegalQueryException; import org.hisp.dhis.common.OrganisationUnitDescendants; import org.hisp.dhis.common.OrganisationUnitSelectionMode; +import org.hisp.dhis.common.UID; import org.hisp.dhis.common.UserOrgUnitType; import org.hisp.dhis.common.ValueType; import org.hisp.dhis.common.cache.CacheStrategy; @@ -462,7 +463,7 @@ public static AggregateDataExchange getAggregateDataExchange(char uniqueCharacte .setVisualization("JHKuBWP20RO") .setDx(newArrayList("LrDpG50RAU9", "uR5HCiJhQ1w")) .setPe(newArrayList("202201", "202202")) - .setOu(newArrayList("G9BuXqtNeeb", "jDgiLmYwPDm")) + .setOu(newArrayList(UID.of("G9BuXqtNeeb"), UID.of("jDgiLmYwPDm"))) .setFilters( newArrayList( new Filter() diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/MetadataImportExportControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/MetadataImportExportControllerTest.java index db4f68564b6e..a60785953b0b 100644 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/MetadataImportExportControllerTest.java +++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/MetadataImportExportControllerTest.java @@ -565,6 +565,21 @@ void testPatchAggregateDataExchange() { assertEquals("External basic auth data exchange updated", object.getString("name").string()); } + @Test + @DisplayName("Should return conflict when source request ou contains an invalid UID") + void testSourceRequestOuInvalidUid() { + JsonWebMessage message = + assertWebMessage( + HttpStatus.CONFLICT, + POST( + "/metadata/", + "{'aggregateDataExchanges': [{'id': 'iFOyIpQciyk', 'name': 'Test exchange'," + + "'source': {'requests': [{'name': 'R1'," + + "'dx': ['fbfJHSPpUQD'], 'pe': ['202201'], 'ou': ['1nvalidUid']}]}," + + "'target': {'type': 'INTERNAL'}}]}")); + assertTrue(message.getMessage().contains("1nvalidUid")); + } + @Test @DisplayName( "Should return error E6305 if create a new AggregateDataExchange without authentication" diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/CrudControllerAdvice.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/CrudControllerAdvice.java index 635fe6a6a45e..9bc4f49984c5 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/CrudControllerAdvice.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/CrudControllerAdvice.java @@ -39,6 +39,7 @@ import static org.hisp.dhis.dxf2.webmessage.WebMessageUtils.unauthorized; import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.RuntimeJsonMappingException; import io.github.classgraph.ClassGraph; import jakarta.persistence.PersistenceException; @@ -400,6 +401,7 @@ public WebMessage dataApprovalExceptionHandler(Exception ex) { @ExceptionHandler({ JsonParseException.class, + JsonMappingException.class, MetadataImportException.class, MetadataExportException.class })