diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityService.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityService.java index a3049d059080..37e678dfa5de 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityService.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/DataIntegrityService.java @@ -34,25 +34,9 @@ import org.hisp.dhis.scheduling.JobProgress; /** - * @author Fredrik Fjeld (old API) - * @author Jan Bernitt (new API) + * @author Jan Bernitt */ public interface DataIntegrityService { - /* - * Old API - */ - - /** - * @deprecated Replaced by {@link #getSummaries(Set, long)} and {@link #getDetails(Set, long)}, - * kept for backwards compatibility until new UI exists - */ - @Deprecated(since = "2.38", forRemoval = true) - @Nonnull - FlattenedDataIntegrityReport getReport(Set checks, JobProgress progress); - - /* - * New generic API - */ default @Nonnull Collection getDataIntegrityChecks() { return getDataIntegrityChecks(Set.of()); diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java deleted file mode 100644 index 2ffe5f10e8ea..000000000000 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataintegrity/FlattenedDataIntegrityReport.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (c) 2004-2022, University of Oslo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the name of the HISP project nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.hisp.dhis.dataintegrity; - -import static java.util.stream.Collectors.toMap; -import static java.util.stream.Collectors.toUnmodifiableList; -import static java.util.stream.Collectors.toUnmodifiableMap; - -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.SortedMap; -import java.util.TreeMap; -import javax.annotation.Nonnull; -import org.hisp.dhis.dataintegrity.DataIntegrityDetails.DataIntegrityIssue; -import org.hisp.dhis.webmessage.WebMessageResponse; - -/** - * Flattened, easily serializable object derivable from the more complex DataIntegrityReport. Use an - * instance of this object to serialize and deliver a DataIntegrityReport. - * - * @author Halvdan Hoem Grelland - */ -public class FlattenedDataIntegrityReport implements WebMessageResponse { - @JsonProperty private final List dataElementsWithoutDataSet; - - @JsonProperty private final List dataElementsWithoutGroups; - - @JsonProperty - private final Map> dataElementsAssignedToDataSetsWithDifferentPeriodTypes; - - @JsonProperty private final Map> dataElementsViolatingExclusiveGroupSets; - - @JsonProperty private final Map> dataElementsInDataSetNotInForm; - - @JsonProperty private final List invalidCategoryCombos; - - @JsonProperty private final List dataSetsNotAssignedToOrganisationUnits; - - @JsonProperty private final List> indicatorsWithIdenticalFormulas; - - @JsonProperty private final List indicatorsWithoutGroups; - - @JsonProperty private final Map invalidIndicatorNumerators; - - @JsonProperty private final Map invalidIndicatorDenominators; - - @JsonProperty private final Map> indicatorsViolatingExclusiveGroupSets; - - @JsonProperty private final List duplicatePeriods; - - @JsonProperty private final List organisationUnitsWithCyclicReferences; - - @JsonProperty private final List orphanedOrganisationUnits; - - @JsonProperty private final List organisationUnitsWithoutGroups; - - @JsonProperty - private final Map> organisationUnitsViolatingExclusiveGroupSets; - - @JsonProperty private final List organisationUnitGroupsWithoutGroupSets; - - @JsonProperty private final List validationRulesWithoutGroups; - - @JsonProperty private final Map invalidValidationRuleLeftSideExpressions; - - @JsonProperty private final Map invalidValidationRuleRightSideExpressions; - - @JsonProperty private final Map invalidProgramIndicatorExpressions; - - @JsonProperty private final List programIndicatorsWithNoExpression; - - @JsonProperty private final Map invalidProgramIndicatorFilters; - - @JsonProperty private final Map> programRulesWithNoCondition; - - @JsonProperty private final Map> programRulesWithNoPriority; - - @JsonProperty private final Map> programRulesWithNoAction; - - @JsonProperty private final Map> programRuleVariablesWithNoDataElement; - - @JsonProperty private final Map> programRuleVariablesWithNoAttribute; - - @JsonProperty private final Map> programRuleActionsWithNoDataObject; - - @JsonProperty private final Map> programRuleActionsWithNoNotification; - - @JsonProperty private final Map> programRuleActionsWithNoSectionId; - - @JsonProperty private final Map> programRuleActionsWithNoStageId; - - public FlattenedDataIntegrityReport(Map detailsByName) { - // name/UID only - this.dataElementsWithoutDataSet = - listOfDisplayNameWithUid(detailsByName.get("data_elements_without_datasets")); - this.dataElementsWithoutGroups = - listOfDisplayNameWithUid(detailsByName.get("data_elements_aggregate_no_groups")); - this.invalidCategoryCombos = - listOfDisplayNameWithUid(detailsByName.get("invalid_category_combos")); - this.dataSetsNotAssignedToOrganisationUnits = - listOfDisplayNameOrUid(detailsByName.get("datasets_not_assigned_to_org_units")); - this.indicatorsWithoutGroups = - listOfDisplayNameOrUid(detailsByName.get("indicators_not_grouped")); - this.duplicatePeriods = - listOfDisplayNameOrUid(detailsByName.get("periods_same_start_date_period_type")); - this.organisationUnitsWithCyclicReferences = - listOfDisplayNameOrUid( - detailsByName.get(DataIntegrityCheckType.ORG_UNITS_WITH_CYCLIC_REFERENCES.getName())); - this.orphanedOrganisationUnits = - listOfDisplayNameWithUid(detailsByName.get("orgunits_orphaned")); - // Replaced with SQL based equivalent - this.organisationUnitsWithoutGroups = - listOfDisplayNameWithUid(detailsByName.get("organisation_units_without_groups")); - this.organisationUnitGroupsWithoutGroupSets = - listOfDisplayNameOrUid(detailsByName.get("org_units_not_in_compulsory_group_sets")); - this.validationRulesWithoutGroups = - listOfDisplayNameOrUid(detailsByName.get("validation_rules_without_groups")); - this.programIndicatorsWithNoExpression = - listOfDisplayNameOrUid(detailsByName.get("program_indicators_without_expression")); - - // grouped name/UID - this.indicatorsWithIdenticalFormulas = - groupedListOfDisplayNameOrUid( - detailsByName.get(DataIntegrityCheckType.INDICATORS_WITH_IDENTICAL_FORMULAS.getName())); - - // comments ny name/UID - this.invalidIndicatorNumerators = - mapOfCommentByDisplayNameOrUid( - detailsByName.get(DataIntegrityCheckType.INDICATORS_WITH_INVALID_NUMERATOR.getName())); - this.invalidIndicatorDenominators = - mapOfCommentByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.INDICATORS_WITH_INVALID_DENOMINATOR.getName())); - this.invalidValidationRuleLeftSideExpressions = - mapOfCommentByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.VALIDATION_RULES_WITH_INVALID_LEFT_SIDE_EXPRESSION - .getName())); - this.invalidValidationRuleRightSideExpressions = - mapOfCommentByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.VALIDATION_RULES_WITH_INVALID_RIGHT_SIDE_EXPRESSION - .getName())); - this.invalidProgramIndicatorExpressions = - mapOfCommentByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_INDICATORS_WITH_INVALID_EXPRESSIONS.getName())); - this.invalidProgramIndicatorFilters = - mapOfCommentByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_INDICATORS_WITH_INVALID_FILTERS.getName())); - this.dataElementsAssignedToDataSetsWithDifferentPeriodTypes = - mapOfRefsByDisplayNameOrUid( - detailsByName.get("data_elements_aggregate_with_different_period_types")); - this.dataElementsViolatingExclusiveGroupSets = - mapOfRefsByDisplayNameOrUid( - detailsByName.get("data_elements_violating_exclusive_group_sets")); - this.dataElementsInDataSetNotInForm = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.DATA_ELEMENTS_IN_DATA_SET_NOT_IN_FORM.getName())); - this.indicatorsViolatingExclusiveGroupSets = - mapOfRefsByDisplayNameOrUid(detailsByName.get("indicators_violating_exclusive_group_sets")); - this.organisationUnitsViolatingExclusiveGroupSets = - mapOfRefsByDisplayNameOrUid( - detailsByName.get("organisation_units_violating_exclusive_group_sets")); - this.programRulesWithNoCondition = - mapOfRefsByDisplayNameOrUid(detailsByName.get("program_rules_without_condition")); - this.programRulesWithNoPriority = - mapOfRefsByDisplayNameOrUid(detailsByName.get("program_rules_no_priority")); - this.programRulesWithNoAction = - mapOfRefsByDisplayNameOrUid(detailsByName.get("program_rules_no_action")); - this.programRuleVariablesWithNoDataElement = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_RULE_VARIABLES_WITHOUT_DATA_ELEMENT.getName())); - this.programRuleVariablesWithNoAttribute = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_RULE_VARIABLES_WITHOUT_ATTRIBUTE.getName())); - this.programRuleActionsWithNoDataObject = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_RULE_ACTIONS_WITHOUT_DATA_OBJECT.getName())); - this.programRuleActionsWithNoNotification = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_RULE_ACTIONS_WITHOUT_NOTIFICATION.getName())); - this.programRuleActionsWithNoSectionId = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_RULE_ACTIONS_WITHOUT_SECTION.getName())); - this.programRuleActionsWithNoStageId = - mapOfRefsByDisplayNameOrUid( - detailsByName.get( - DataIntegrityCheckType.PROGRAM_RULE_ACTIONS_WITHOUT_STAGE_ID.getName())); - } - - @Nonnull - @Override - public Class getResponseClassType() { - return FlattenedDataIntegrityReport.class; - } - - private List listOfDisplayNameOrUid(DataIntegrityDetails details) { - return details == null - ? null - : details.getIssues().stream() - .map(DataIntegrityIssue::getName) - .collect(toUnmodifiableList()); - } - - private List listOfDisplayNameWithUid(DataIntegrityDetails details) { - return details == null - ? null - : details.getIssues().stream() - .map(issue -> issue.getName() + ":" + issue.getId()) - .collect(toUnmodifiableList()); - } - - private List> groupedListOfDisplayNameOrUid(DataIntegrityDetails details) { - return details == null - ? null - : details.getIssues().stream() - .map(DataIntegrityIssue::getRefs) - .collect(toUnmodifiableList()); - } - - private static Map mapOfCommentByDisplayNameOrUid(DataIntegrityDetails details) { - return details == null - ? null - : details.getIssues().stream() - .collect( - toUnmodifiableMap(DataIntegrityIssue::getName, DataIntegrityIssue::getComment)); - } - - private static SortedMap> mapOfRefsByDisplayNameOrUid( - DataIntegrityDetails details) { - return details == null - ? null - : details.getIssues().stream() - .collect( - toMap( - DataIntegrityIssue::getName, - DataIntegrityIssue::getRefs, - FlattenedDataIntegrityReport::concatLists, - TreeMap::new)); - } - - /** - * On a "collision" (key already exists/has a value) we do combine both lists. At this point we - * have to assume the passed {@link Collection}s are read-only. - */ - private static List concatLists(List a, List b) { - List both = new ArrayList<>(); - both.addAll(a); - both.addAll(b); - return both; - } -} diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/scheduling/parameters/DataIntegrityJobParameters.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/scheduling/parameters/DataIntegrityJobParameters.java index 3241a55639f6..fec5c6c9868b 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/scheduling/parameters/DataIntegrityJobParameters.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/scheduling/parameters/DataIntegrityJobParameters.java @@ -51,11 +51,11 @@ public enum DataIntegrityReportType { DETAILS } - @JsonProperty(required = false) + @JsonProperty @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) private DataIntegrityReportType type; - @JsonProperty(required = false) + @JsonProperty @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) private Set checks; } diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/DefaultDataIntegrityService.java b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/DefaultDataIntegrityService.java index ea7ad4bca3ef..c1936e629170 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/DefaultDataIntegrityService.java +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/DefaultDataIntegrityService.java @@ -45,7 +45,6 @@ import static org.hisp.dhis.scheduling.JobProgress.FailurePolicy.SKIP_ITEM; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashSet; @@ -512,23 +511,6 @@ Set addSQLChecksToFlattedReport() { return checks; } - @Nonnull - @Override - @Transactional(readOnly = true) - public FlattenedDataIntegrityReport getReport(Set checks, JobProgress progress) { - if (checks == null || checks.isEmpty()) { - // report only needs these - checks = - Arrays.stream(DataIntegrityCheckType.values()) - .map(DataIntegrityCheckType::getName) - .collect(Collectors.toSet()); - // Add additional SQL based checks here - checks.addAll(addSQLChecksToFlattedReport()); - } - runDetailsChecks(checks, progress); - return new FlattenedDataIntegrityReport(getDetails(checks, -1L)); - } - /** Get all ProgramIndicators with invalid expressions. */ List getInvalidProgramIndicatorExpressions() { return getInvalidProgramIndicators( diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/jobs/DataIntegrityJob.java b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/jobs/DataIntegrityJob.java index 9e418a69b1cb..849747bb847f 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/jobs/DataIntegrityJob.java +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/dataintegrity/jobs/DataIntegrityJob.java @@ -29,17 +29,13 @@ import java.util.Set; import lombok.AllArgsConstructor; -import org.hisp.dhis.commons.timer.SystemTimer; -import org.hisp.dhis.commons.timer.Timer; import org.hisp.dhis.dataintegrity.DataIntegrityService; -import org.hisp.dhis.dataintegrity.FlattenedDataIntegrityReport; import org.hisp.dhis.scheduling.Job; import org.hisp.dhis.scheduling.JobConfiguration; import org.hisp.dhis.scheduling.JobProgress; import org.hisp.dhis.scheduling.JobType; import org.hisp.dhis.scheduling.parameters.DataIntegrityJobParameters; import org.hisp.dhis.scheduling.parameters.DataIntegrityJobParameters.DataIntegrityReportType; -import org.hisp.dhis.system.notification.Notifier; import org.springframework.stereotype.Component; /** @@ -49,9 +45,8 @@ @Component @AllArgsConstructor public class DataIntegrityJob implements Job { - private final DataIntegrityService dataIntegrityService; - private final Notifier notifier; + private final DataIntegrityService dataIntegrityService; @Override public JobType getJobType() { @@ -64,25 +59,10 @@ public void execute(JobConfiguration config, JobProgress progress) { Set checks = parameters == null ? Set.of() : parameters.getChecks(); DataIntegrityReportType type = parameters == null ? null : parameters.getType(); - if (type == null || type == DataIntegrityReportType.REPORT) { - runReport(config, progress, checks); - } else if (type == DataIntegrityReportType.SUMMARY) { + if (type != DataIntegrityReportType.DETAILS) { dataIntegrityService.runSummaryChecks(checks, progress); } else { dataIntegrityService.runDetailsChecks(checks, progress); } } - - private void runReport(JobConfiguration config, JobProgress progress, Set checks) { - Timer timer = new SystemTimer().start(); - notifier.notify(config, "Starting data integrity job"); - - FlattenedDataIntegrityReport report = dataIntegrityService.getReport(checks, progress); - - timer.stop(); - - notifier - .notify(config, "Data integrity checks completed in " + timer + ".", true) - .addJobSummary(config, report, FlattenedDataIntegrityReport.class); - } } diff --git a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/webmessage/WebMessage.java b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/webmessage/WebMessage.java index 05dde92389ee..bce965e9bf1e 100644 --- a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/webmessage/WebMessage.java +++ b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/webmessage/WebMessage.java @@ -36,7 +36,6 @@ import lombok.Getter; import org.hisp.dhis.common.DxfNamespaces; import org.hisp.dhis.common.OpenApi; -import org.hisp.dhis.dataintegrity.FlattenedDataIntegrityReport; import org.hisp.dhis.dxf2.common.ImportTypeSummary; import org.hisp.dhis.dxf2.geojson.GeoJsonImportReport; import org.hisp.dhis.dxf2.importsummary.ImportSummaries; @@ -91,7 +90,6 @@ public class WebMessage extends WebResponse { ApiTokenCreationResponse.class, ErrorReportsWebMessageResponse.class, FileResourceWebMessageResponse.class, - FlattenedDataIntegrityReport.class, GeoJsonImportReport.class, ImportCountWebMessageResponse.class, ImportReportWebMessageResponse.class, diff --git a/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/webapi/json/domain/JsonDataIntegrityReport.java b/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/webapi/json/domain/JsonDataIntegrityReport.java deleted file mode 100644 index 86d89b48778b..000000000000 --- a/dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/test/webapi/json/domain/JsonDataIntegrityReport.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2004-2022, University of Oslo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the name of the HISP project nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.hisp.dhis.test.webapi.json.domain; - -import org.hisp.dhis.jsontree.JsonArray; -import org.hisp.dhis.jsontree.JsonList; -import org.hisp.dhis.jsontree.JsonMap; -import org.hisp.dhis.jsontree.JsonMultiMap; -import org.hisp.dhis.jsontree.JsonObject; -import org.hisp.dhis.jsontree.JsonString; - -/** - * JSON equivalent of the {@link org.hisp.dhis.dataintegrity.FlattenedDataIntegrityReport}. - * - * @author Jan Bernitt - */ -public interface JsonDataIntegrityReport extends JsonObject { - - default JsonList getDataElementsWithoutDataSet() { - return getList("dataElementsWithoutDataSet", JsonString.class); - } - - default JsonList getDataElementsWithoutGroups() { - return getList("dataElementsWithoutGroups", JsonString.class); - } - - default JsonMultiMap getDataElementsAssignedToDataSetsWithDifferentPeriodTypes() { - return getMultiMap("dataElementsAssignedToDataSetsWithDifferentPeriodTypes", JsonString.class); - } - - default JsonMultiMap getDataElementsViolatingExclusiveGroupSets() { - return getMultiMap("dataElementsViolatingExclusiveGroupSets", JsonString.class); - } - - default JsonMultiMap getDataElementsInDataSetNotInForm() { - return getMultiMap("dataElementsInDataSetNotInForm", JsonString.class); - } - - default JsonList getInvalidCategoryCombos() { - return getList("invalidCategoryCombos", JsonString.class); - } - - default JsonList getDataSetsNotAssignedToOrganisationUnits() { - return getList("dataSetsNotAssignedToOrganisationUnits", JsonString.class); - } - - default JsonList getIndicatorsWithIdenticalFormulas() { - return getList("indicatorsWithIdenticalFormulas", JsonArray.class); - } - - default JsonList getIndicatorsWithoutGroups() { - return getList("indicatorsWithoutGroups", JsonString.class); - } - - default JsonMap getInvalidIndicatorNumerators() { - return getMap("invalidIndicatorNumerators", JsonString.class); - } - - default JsonMap getInvalidIndicatorDenominators() { - return getMap("invalidIndicatorDenominators", JsonString.class); - } - - default JsonMultiMap getIndicatorsViolatingExclusiveGroupSets() { - return getMultiMap("indicatorsViolatingExclusiveGroupSets", JsonString.class); - } - - default JsonList getDuplicatePeriods() { - return getList("duplicatePeriods", JsonString.class); - } - - default JsonList getOrganisationUnitsWithCyclicReferences() { - return getList("organisationUnitsWithCyclicReferences", JsonString.class); - } - - default JsonList getOrphanedOrganisationUnits() { - return getList("orphanedOrganisationUnits", JsonString.class); - } - - default JsonList getOrganisationUnitsWithoutGroups() { - return getList("organisationUnitsWithoutGroups", JsonString.class); - } - - default JsonMultiMap getOrganisationUnitsViolatingExclusiveGroupSets() { - return getMultiMap("organisationUnitsViolatingExclusiveGroupSets", JsonString.class); - } - - default JsonList getOrganisationUnitGroupsWithoutGroupSets() { - return getList("organisationUnitGroupsWithoutGroupSets", JsonString.class); - } - - default JsonList getValidationRulesWithoutGroups() { - return getList("validationRulesWithoutGroups", JsonString.class); - } - - default JsonMap getInvalidValidationRuleLeftSideExpressions() { - return getMap("invalidValidationRuleLeftSideExpressions", JsonString.class); - } - - default JsonMap getInvalidValidationRuleRightSideExpressions() { - return getMap("invalidValidationRuleRightSideExpressions", JsonString.class); - } - - default JsonMap getInvalidProgramIndicatorExpressions() { - return getMap("invalidProgramIndicatorExpressions", JsonString.class); - } - - default JsonList getProgramIndicatorsWithNoExpression() { - return getList("programIndicatorsWithNoExpression", JsonString.class); - } - - default JsonMap getInvalidProgramIndicatorFilters() { - return getMap("invalidProgramIndicatorFilters", JsonString.class); - } - - default JsonMultiMap getProgramRulesWithNoCondition() { - return getMultiMap("programRulesWithNoCondition", JsonString.class); - } - - default JsonMultiMap getProgramRulesWithNoPriority() { - return getMultiMap("programRulesWithNoPriority", JsonString.class); - } - - default JsonMultiMap getProgramRulesWithNoAction() { - return getMultiMap("programRulesWithNoAction", JsonString.class); - } - - default JsonMultiMap getProgramRuleVariablesWithNoDataElement() { - return getMultiMap("programRuleVariablesWithNoDataElement", JsonString.class); - } - - default JsonMultiMap getProgramRuleVariablesWithNoAttribute() { - return getMultiMap("programRuleVariablesWithNoAttribute", JsonString.class); - } - - default JsonMultiMap getProgramRuleActionsWithNoDataObject() { - return getMultiMap("programRuleActionsWithNoDataObject", JsonString.class); - } - - default JsonMultiMap getProgramRuleActionsWithNoNotification() { - return getMultiMap("programRuleActionsWithNoNotification", JsonString.class); - } - - default JsonMultiMap getProgramRuleActionsWithNoSectionId() { - return getMultiMap("programRuleActionsWithNoSectionId", JsonString.class); - } - - default JsonMultiMap getProgramRuleActionsWithNoStageId() { - return getMultiMap("programRuleActionsWithNoStageId", JsonString.class); - } -} diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/dataintegrity/DataIntegrityReportControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/dataintegrity/DataIntegrityReportControllerTest.java deleted file mode 100644 index 1a7fed302eb8..000000000000 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/dataintegrity/DataIntegrityReportControllerTest.java +++ /dev/null @@ -1,662 +0,0 @@ -/* - * Copyright (c) 2004-2022, University of Oslo - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * Neither the name of the HISP project nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.hisp.dhis.webapi.controller.dataintegrity; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static org.hisp.dhis.common.CodeGenerator.generateUid; -import static org.hisp.dhis.http.HttpAssertions.assertStatus; -import static org.hisp.dhis.test.utils.Assertions.assertContainsOnly; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import java.util.Map; -import org.hisp.dhis.http.HttpStatus; -import org.hisp.dhis.jsontree.JsonNodeType; -import org.hisp.dhis.jsontree.JsonObject; -import org.hisp.dhis.jsontree.JsonString; -import org.hisp.dhis.organisationunit.OrganisationUnit; -import org.hisp.dhis.organisationunit.OrganisationUnitStore; -import org.hisp.dhis.test.webapi.json.domain.JsonDataIntegrityReport; -import org.hisp.dhis.webapi.controller.DataIntegrityController; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * Tests the {@link DataIntegrityController} API with focus API returning {@link - * org.hisp.dhis.dataintegrity.FlattenedDataIntegrityReport}. - * - * @author Jan Bernitt - */ -class DataIntegrityReportControllerTest extends AbstractDataIntegrityIntegrationTest { - /** Needed to create cyclic references for org units */ - @Autowired private OrganisationUnitStore organisationUnitStore; - - @Test - void testNoViolations() { - // if the report does not have any strings in the JSON tree there are no - // errors since all collection/maps have string values - JsonDataIntegrityReport report = getDataIntegrityReport(); - assertEquals(1, report.node().count(JsonNodeType.STRING)); - assertEquals("FlattenedDataIntegrityReport", report.getString("responseType").string()); - } - - @Test - void testDataElementChecksOnly() { - JsonDataIntegrityReport report = getDataIntegrityReport("/dataIntegrity?checks=data-element*"); - assertEquals(6, report.size()); - assertTrue( - report.has( - "responseType", - "dataElementsWithoutDataSet", - "dataElementsWithoutGroups", - "dataElementsAssignedToDataSetsWithDifferentPeriodTypes", - "dataElementsViolatingExclusiveGroupSets", - "dataElementsInDataSetNotInForm")); - } - - @Test - void testExclusiveGroupsChecksOnly() { - JsonDataIntegrityReport report = - getDataIntegrityReport("/dataIntegrity?checks=*exclusive-group*"); - assertEquals(4, report.size()); - assertTrue( - report.has( - "responseType", - "dataElementsViolatingExclusiveGroupSets", - "indicatorsViolatingExclusiveGroupSets", - "organisationUnitsViolatingExclusiveGroupSets")); - } - - @Test - void testPeriodsDuplicatesOnly() { - JsonDataIntegrityReport report = - getDataIntegrityReport("/dataIntegrity?checks=periods_same_start_date_period_type"); - assertEquals(2, report.size()); - assertTrue(report.getArray("duplicatePeriods").exists()); - } - - @Test - void testOrphanedOrganisationUnits() { - // should match: - String ouId = addOrganisationUnit("OrphanedUnit"); - // should not match: - String ouRootId = addOrganisationUnit("root"); - addOrganisationUnit("leaf", ouRootId); - assertEquals( - singletonList("OrphanedUnit:" + ouId), - getDataIntegrityReport().getOrphanedOrganisationUnits().toList(JsonString::string)); - } - - @Test - void testOrganisationUnitsWithoutGroups() { - // should match: - String ouId = addOrganisationUnit("noGroupSet"); - // should not match: - addOrganisationUnitGroup("group", addOrganisationUnit("hasGroupSet")); - List results = - getDataIntegrityReport().getOrganisationUnitsWithoutGroups().toList(JsonString::string); - assertEquals(singletonList("noGroupSet:" + ouId), results); - } - - @Test - void testOrganisationUnitsWithCyclicReferences() { - String ouIdA = addOrganisationUnit("A"); - String ouIdB = addOrganisationUnit("B", ouIdA); - // create cyclic references (seemingly not possible via REST API) - OrganisationUnit ouA = organisationUnitStore.getByUid(ouIdA); - OrganisationUnit ouB = organisationUnitStore.getByUid(ouIdB); - ouA.setParent(ouB); - ouB.getChildren().add(ouA); - organisationUnitStore.save(ouB); - assertContainsOnly( - List.of("A:" + ouIdA, "B:" + ouIdB), - getDataIntegrityReport() - .getOrganisationUnitsWithCyclicReferences() - .toList(JsonString::string)); - } - - @Test - void testOrganisationUnitsViolatingExclusiveGroupSets() { - String ouIdA = addOrganisationUnit("A"); - String ouIdB = addOrganisationUnit("B"); - addOrganisationUnit("C"); - // all groups created are compulsory - String groupA0Id = addOrganisationUnitGroup("A0", ouIdA); - String groupB1Id = addOrganisationUnitGroup("B1", ouIdB); - String groupB2Id = addOrganisationUnitGroup("B2", ouIdB); - addOrganisationUnitGroupSet("K", groupA0Id); - addOrganisationUnitGroupSet("X", groupB1Id, groupB2Id); - assertEquals( - Map.of("B", asList("B1:" + groupB1Id, "B2:" + groupB2Id)), - getDataIntegrityReport() - .getOrganisationUnitsViolatingExclusiveGroupSets() - .toMap(JsonString::string, String::compareTo)); - } - - @Test - void testDataElementsInDatasetsWithDifferentFrequencies() { - String defaultCatCombo = getDefaultCatCombo(); - - String dataElementA = - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElements", - "{ 'name': 'ANC1', 'shortName': 'ANC1', 'valueType' : 'NUMBER'," - + "'domainType' : 'AGGREGATE', 'aggregationType' : 'SUM' }")); - - String dataset1_uid = generateUid(); - - String dataset1 = - "{ 'id':'" - + dataset1_uid - + "', 'name': 'Test Monthly', 'shortName': 'Test Monthly', 'periodType' : 'Monthly'," - + "'categoryCombo' : {'id': '" - + defaultCatCombo - + "'}, " - + "'dataSetElements' : [{'dataSet' : {'id':'" - + dataset1_uid - + "'}, 'id':'" - + generateUid() - + "', 'dataElement': {'id' : '" - + dataElementA - + "'}}]}"; - - assertStatus(HttpStatus.CREATED, POST("/dataSets", dataset1)); - - String dataset2_uid = generateUid(); - String dataset2 = - "{ 'id':'" - + dataset2_uid - + "', 'name': 'Test Quarterly', 'shortName': 'Test Quarterly', 'periodType' : 'Quarterly'," - + "'categoryCombo' : {'id': '" - + defaultCatCombo - + "'}, " - + "'dataSetElements' : [{'dataSet' : {'id':'" - + dataset2_uid - + "'}, 'id':'" - + generateUid() - + "', 'dataElement': {'id' : '" - + dataElementA - + "'}}]}"; - - assertStatus(HttpStatus.CREATED, POST("/dataSets", dataset2)); - - Map> expected = - Map.of("ANC1", List.of(dataset1_uid, dataset2_uid).stream().sorted().toList()); - - Map> actual = - getDataIntegrityReport() - .getDataElementsAssignedToDataSetsWithDifferentPeriodTypes() - .toMap(JsonString::string, String::compareTo); - - assertEquals(expected, actual); - } - - private String addOrganisationUnit(String name) { - return assertStatus( - HttpStatus.CREATED, - POST( - "/organisationUnits", - "{'name':'" + name + "', 'shortName':'" + name + "', 'openingDate':'2021'}")); - } - - private String addOrganisationUnit(String name, String parentId) { - return assertStatus( - HttpStatus.CREATED, - POST( - "/organisationUnits", - "{'name':'" - + name - + "', 'shortName':'" - + name - + "', 'openingDate':'2021', 'parent': " - + objectReference(parentId) - + " }")); - } - - private String addOrganisationUnitGroup(String name, String... memberIds) { - return assertStatus( - HttpStatus.CREATED, - POST( - "/organisationUnitGroups", - "{'name':'" - + name - + "', 'shortName':'" - + name - + "', 'organisationUnits': " - + objectReferences(memberIds) - + "}")); - } - - private String addOrganisationUnitGroupSet(String name, String... groupIds) { - // OBS! note that we make them compulsory - return assertStatus( - HttpStatus.CREATED, - POST( - "/organisationUnitGroupSets", - "{'name':'" - + name - + "', 'shortName':'" - + name - + "', 'compulsory': true, 'organisationUnitGroups': " - + objectReferences(groupIds) - + "}")); - } - - @Test - void testDataElementsNoGroups() { - - String dataElementA = - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElements", - "{ 'name': 'ANC1', 'shortName': 'ANC1', 'valueType' : 'NUMBER'," - + "'domainType' : 'AGGREGATE', 'aggregationType' : 'SUM' }")); - - String dataElementB = - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElements", - "{ 'name': 'ANC2', 'shortName': 'ANC2', 'valueType' : 'NUMBER'," - + "'domainType' : 'AGGREGATE', 'aggregationType' : 'SUM' }")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElementGroups", - "{ 'name': 'ANC', 'shortName': 'ANC' , 'dataElements' : [{'id' : '" - + dataElementA - + "'}]}")); - List results = - getDataIntegrityReport().getDataElementsWithoutGroups().toList(JsonString::string); - assertEquals(singletonList("ANC2" + ":" + dataElementB), results); - } - - @Test - void testDataElementsNoDatasets() { - - String defaultCatCombo = getDefaultCatCombo(); - String dataSetA = generateUid(); - - String dataElementA = - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElements", - "{ 'name': 'ANC1', 'shortName': 'ANC1', 'valueType' : 'NUMBER'," - + "'domainType' : 'AGGREGATE', 'aggregationType' : 'SUM' }")); - String dataElementB = - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElements", - "{ 'name': 'ANC2', 'shortName': 'ANC2', 'valueType' : 'NUMBER'," - + "'domainType' : 'AGGREGATE', 'aggregationType' : 'SUM' }")); - String datasetMetadata = - "{ 'id':'" - + dataSetA - + "', 'name': 'Test Monthly', 'shortName': 'Test Monthly', 'periodType' : 'Monthly'," - + "'categoryCombo' : {'id': '" - + defaultCatCombo - + "'}, " - + "'dataSetElements' : [{'dataSet' : {'id':'" - + dataSetA - + "'}, 'id':'" - + generateUid() - + "', 'dataElement': {'id' : '" - + dataElementA - + "'}}]}"; - - assertStatus(HttpStatus.CREATED, POST("/dataSets", datasetMetadata)); - - List results = - getDataIntegrityReport().getDataElementsWithoutDataSet().toList(JsonString::string); - assertEquals(List.of("ANC2" + ":" + dataElementB), results); - } - - @Test - void testDatasetsNotAssignedToOrgUnits() { - String defaultCatCombo = getDefaultCatCombo(); - String dataSetUID = generateUid(); - String dataElementA = - assertStatus( - HttpStatus.CREATED, - POST( - "/dataElements", - "{ 'name': 'ANC1', 'shortName': 'ANC1', 'valueType' : 'NUMBER'," - + "'domainType' : 'AGGREGATE', 'aggregationType' : 'SUM' }")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/dataSets", - "{ 'id' : '" - + dataSetUID - + "', 'name': 'Test', 'shortName': 'Test', 'periodType' : 'Monthly', 'categoryCombo' : {'id': '" - + defaultCatCombo - + "'}, " - + " 'dataSetElements': [{ 'dataSet': { 'id': '" - + dataSetUID - + "'}, 'dataElement': { 'id': '" - + dataElementA - + "'}}]}")); - List results = - getDataIntegrityReport() - .getDataSetsNotAssignedToOrganisationUnits() - .toList(JsonString::string); - assertEquals(List.of("Test"), results); - } - - @Test - void testInvalidCategoryCombos() { - String categoryTaste = - assertStatus( - HttpStatus.CREATED, - POST( - "/categories", - "{ 'name': 'Taste', 'shortName': 'Taste', 'dataDimensionType': 'DISAGGREGATION' }")); - - String testCatCombo = - assertStatus( - HttpStatus.CREATED, - POST( - "/categoryCombos", - "{ 'name' : 'Tasteless', " - + "'dataDimensionType' : 'DISAGGREGATION', 'categories' : [" - + " {'id' : '" - + categoryTaste - + "'}]} ")); - List results = - getDataIntegrityReport().getInvalidCategoryCombos().toList(JsonString::string); - assertEquals(List.of("Tasteless" + ":" + testCatCombo), results); - } - - @Test - void testIndicatorsNotInAnyGroups() { - String indicatorTypeA = - assertStatus( - HttpStatus.CREATED, - POST("/indicatorTypes", "{ 'name': 'Per cent', 'factor' : 100, 'number' : false }")); - - String indicatorA = - assertStatus( - HttpStatus.CREATED, - POST( - "/indicators", - "{ 'name': 'Indicator A', 'shortName': 'Indicator A', 'indicatorType' : {'id' : '" - + indicatorTypeA - + "'}," - + " 'numerator' : 'abc123', 'numeratorDescription' : 'One', 'denominator' : 'abc123', " - + "'denominatorDescription' : 'Zero'} }")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/indicators", - "{ 'name': 'Indicator B', 'shortName': 'Indicator B', 'indicatorType' : {'id' : '" - + indicatorTypeA - + "'}," - + " 'numerator' : 'abc123', 'numeratorDescription' : 'One', 'denominator' : 'abc123', " - + "'denominatorDescription' : 'Zero'}")); - assertStatus( - HttpStatus.CREATED, - POST( - "/indicatorGroups", - "{ 'name' : 'An indicator group', 'indicators' : [{'id' : '" + indicatorA + "'}]}")); - - List results = - getDataIntegrityReport().getIndicatorsWithoutGroups().toList(JsonString::string); - assertEquals(List.of("Indicator B"), results); - } - - @Test - void testIndicatorsViolateExclusiveGroups() { - String indicatorTypeA = - assertStatus( - HttpStatus.CREATED, - POST( - "/indicatorTypes", - """ - { - "name": "Per cent", - "factor": 100, - "number": false - } - """ - .formatted())); - - String indicatorA = createSimpleIndicator("Indicator A", indicatorTypeA); - String indicatorB = createSimpleIndicator("Indicator B", indicatorTypeA); - String indicatorGroupA = - assertStatus( - HttpStatus.CREATED, - POST( - "/indicatorGroups", - // language=JSON - """ - { - "name": "Group A", - "shortName" : "Group A", - "indicators": [ - { - "id": "%s" - }, - { - "id": "%s" - } - ] - } - """ - .formatted(indicatorA, indicatorB))); - - String indicatorGroupB = - assertStatus( - HttpStatus.CREATED, - POST( - "/indicatorGroups", - // language=JSON - """ - { - "name": "Group B", - "shortName" : "Group B", - "indicators": [ - { - "id": "%s" - } - ] - } - """ - .formatted(indicatorB))); - - assertStatus( - HttpStatus.CREATED, - POST( - "/indicatorGroupSets", - // language=JSON - """ - { - "name": "Indicator Group Set", - "shortName": "Indicator Group Set", - "indicatorGroups": [ - { - "id": "%s" - }, - { - "id": "%s" - } - ] - } - """ - .formatted(indicatorGroupA, indicatorGroupB))); - final Map> expectedResults = - Map.of("Indicator B", List.of("Group A:" + indicatorGroupA, "Group B:" + indicatorGroupB)); - // Test for program rules with no condition - Map> results = - getDataIntegrityReport() - .getIndicatorsViolatingExclusiveGroupSets() - .toMap(JsonString::string, String::compareTo); - assertEquals(expectedResults, results); - } - - @Test - void testValidationRulesWithoutGroups() { - String validationRule1 = - assertStatus( - HttpStatus.CREATED, - POST( - "/validationRules", - "{'importance':'MEDIUM','operator':'not_equal_to','leftSide':{'missingValueStrategy':'NEVER_SKIP', " - + "" - + "'description':'Test','expression':'#{FTRrcoaog83.qk6n4eMAdtK}'}," - + "'rightSide':{'missingValueStrategy': 'NEVER_SKIP', 'description':'Test1'," - + "'expression':'#{FTRrcoaog83.sqGRzCziswD}'},'periodType':'Monthly','name':'Test rule 1'}")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/validationRules", - "{'importance':'MEDIUM','operator':'not_equal_to','leftSide':{'missingValueStrategy':'NEVER_SKIP', " - + "" - + "'description':'Test','expression':'#{FTRrcoaog83.qk6n4eMAdtK}'}," - + "'rightSide':{'missingValueStrategy': 'NEVER_SKIP', 'description':'Test2'," - + "'expression':'#{FTRrcoaog83.sqGRzCziswD}'},'periodType':'Monthly','name':'Test rule 2'}")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/validationRuleGroups", - "{'name':'Test group', 'description':'Test group', 'validationRules': [{'id': '" - + validationRule1 - + "'}]}")); - - List results = - getDataIntegrityReport().getValidationRulesWithoutGroups().toList(JsonString::string); - assertEquals(List.of("Test rule 2"), results); - } - - @Test - void testProgramRulesWithoutCondition() { - String program = - assertStatus( - HttpStatus.CREATED, - POST( - "/programs", - "{'name':'Test program', 'shortName': 'Test program', 'programType': 'WITHOUT_REGISTRATION'}")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/programRules", - "{'name':'Test rule 1', 'description':'Test rule 1', 'program': {'id': '" - + program - + "'}}")); - - final Map> expectedResults = - Map.of("Test rule 1", List.of("Test program:" + program)); - // Test for program rules with no condition - Map> results = - getDataIntegrityReport() - .getProgramRulesWithNoCondition() - .toMap(JsonString::string, String::compareTo); - assertEquals(expectedResults, results); - - // Test for program rules with no action - Map> results2 = - getDataIntegrityReport() - .getProgramRulesWithNoAction() - .toMap(JsonString::string, String::compareTo); - assertEquals(expectedResults, results2); - - // Test for program rules with no priority - Map> results3 = - getDataIntegrityReport() - .getProgramRulesWithNoPriority() - .toMap(JsonString::string, String::compareTo); - assertEquals(expectedResults, results3); - } - - @Test - void testProgramIndicatorsWithoutExpression() { - String program = - assertStatus( - HttpStatus.CREATED, - POST( - "/programs", - "{'name':'Test program', 'shortName': 'Test program', 'programType': 'WITHOUT_REGISTRATION'}")); - - assertStatus( - HttpStatus.CREATED, - POST( - "/programIndicators", - "{'name':'Test program indicator A', 'shortName': 'Test program indicator A', 'program': {'id': '" - + program - + "'}}")); - // Test for program of indicators with no expression - List results = - getDataIntegrityReport().getProgramIndicatorsWithNoExpression().toList(JsonString::string); - assertEquals(List.of("Test program indicator A"), results); - } - - private JsonDataIntegrityReport getDataIntegrityReport() { - return getDataIntegrityReport("/dataIntegrity"); - } - - private JsonDataIntegrityReport getDataIntegrityReport(String url) { - HttpResponse httpResponse = POST(url); - assertTrue( - httpResponse.location().startsWith("http://localhost/api/dataIntegrity/details?checks=")); - JsonObject response = httpResponse.content().getObject("response"); - String id = response.getString("id").string(); - String jobType = response.getString("jobType").string(); - return GET("/system/taskSummaries/{type}/{id}", jobType, id) - .content() - .as(JsonDataIntegrityReport.class); - } - - private static String objectReferences(String... uids) { - StringBuilder str = new StringBuilder(); - str.append('['); - for (String uid : uids) { - if (str.length() > 1) { - str.append(','); - } - str.append(objectReference(uid)); - } - str.append(']'); - return str.toString(); - } - - private static String objectReference(String uid) { - return String.format("{\"id\":\"%s\"}", uid); - } -} diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java index 8e796e341688..606da5e7e712 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/DataIntegrityController.java @@ -94,7 +94,7 @@ public WebMessage runDataIntegrity( @CurrentUser UserDetails currentUser) throws ConflictException, @OpenApi.Ignore NotFoundException { Set names = getCheckNames(checksBody, checks); - return runDataIntegrityAsync(names, currentUser, DataIntegrityReportType.REPORT) + return runDataIntegrityAsync(names, currentUser, DataIntegrityReportType.SUMMARY) .setLocation("/dataIntegrity/details?checks=" + toChecksList(names)); }