diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityAttributeValueChangeLogQueryParams.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/audit/AuditOperationType.java similarity index 64% rename from dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityAttributeValueChangeLogQueryParams.java rename to dhis-2/dhis-api/src/main/java/org/hisp/dhis/audit/AuditOperationType.java index db704216f83e..c4d2bbfc0e18 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityAttributeValueChangeLogQueryParams.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/audit/AuditOperationType.java @@ -25,34 +25,16 @@ * (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.tracker.export.trackedentity; - -import java.util.ArrayList; -import java.util.List; -import lombok.Data; -import lombok.experimental.Accessors; -import org.hisp.dhis.changelog.ChangeLogType; -import org.hisp.dhis.common.Pager; -import org.hisp.dhis.trackedentity.TrackedEntity; -import org.hisp.dhis.trackedentity.TrackedEntityAttribute; +package org.hisp.dhis.audit; /** - * Encapsulation of a web API request for tracked entity data value audit records. - * - * @author Lars Helge Overland + * @author Halvdan Hoem Grelland + * @author Luca Cambi split Changelog from Audit */ -@Data -@Accessors(chain = true) -public class TrackedEntityAttributeValueChangeLogQueryParams { - private List trackedEntityAttributes = new ArrayList<>(); - - private List trackedEntities = new ArrayList<>(); - - private List auditTypes = new ArrayList<>(); - - private Pager pager; - - public boolean hasPager() { - return pager != null; - } +public enum AuditOperationType { + CREATE, + UPDATE, + DELETE, + READ, + SEARCH } diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/changelog/ChangeLogType.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/changelog/ChangeLogType.java index 7236761f47fe..5ce80dd99e3d 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/changelog/ChangeLogType.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/changelog/ChangeLogType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2022, University of Oslo + * Copyright (c) 2004-2024, University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,14 +27,8 @@ */ package org.hisp.dhis.changelog; -/** - * @author Halvdan Hoem Grelland - * @author Luca Cambi split Changelog from Audit - */ public enum ChangeLogType { CREATE, UPDATE, - DELETE, - READ, - SEARCH + DELETE } diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java index 91af859ab1f3..f18f767f9474 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAudit.java @@ -32,8 +32,8 @@ import com.google.common.base.MoreObjects; import java.util.Date; import java.util.Objects; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.DxfNamespaces; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.organisationunit.OrganisationUnit; @@ -62,7 +62,7 @@ public class DataValueAudit { private Date created; - private ChangeLogType auditType; + private AuditOperationType auditType; // ------------------------------------------------------------------------- // Constructors @@ -71,7 +71,7 @@ public class DataValueAudit { public DataValueAudit() {} public DataValueAudit( - DataValue dataValue, String value, String modifiedBy, ChangeLogType auditType) { + DataValue dataValue, String value, String modifiedBy, AuditOperationType auditType) { this.dataElement = dataValue.getDataElement(); this.period = dataValue.getPeriod(); this.organisationUnit = dataValue.getSource(); @@ -91,7 +91,7 @@ public DataValueAudit( CategoryOptionCombo attributeOptionCombo, String value, String modifiedBy, - ChangeLogType auditType) { + AuditOperationType auditType) { this.dataElement = dataElement; this.period = period; this.organisationUnit = organisationUnit; @@ -277,11 +277,11 @@ public void setCreated(Date created) { @JsonProperty @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public ChangeLogType getAuditType() { + public AuditOperationType getAuditType() { return auditType; } - public void setAuditType(ChangeLogType auditType) { + public void setAuditType(AuditOperationType auditType) { this.auditType = auditType; } } diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditQueryParams.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditQueryParams.java index 100a4e918db7..12a7e42bf702 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditQueryParams.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValueAuditQueryParams.java @@ -31,8 +31,8 @@ import java.util.List; import lombok.Data; import lombok.experimental.Accessors; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.Pager; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.organisationunit.OrganisationUnit; @@ -56,7 +56,7 @@ public class DataValueAuditQueryParams { private CategoryOptionCombo attributeOptionCombo; - private List auditTypes = new ArrayList<>(); + private List auditTypes = new ArrayList<>(); private Pager pager; diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/ApiTrackedEntityAuditService.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/ApiTrackedEntityAuditService.java index 557ee46f032d..936cc9824781 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/ApiTrackedEntityAuditService.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/ApiTrackedEntityAuditService.java @@ -27,7 +27,7 @@ */ package org.hisp.dhis.trackedentity; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; /** * @author Abyot Asalefew Gizaw abyota@gmail.com @@ -38,5 +38,5 @@ public interface ApiTrackedEntityAuditService { String ID = ApiTrackedEntityAuditService.class.getName(); void addTrackedEntityAudit( - TrackedEntity trackedEntity, String username, ChangeLogType changeLogType); + TrackedEntity trackedEntity, String username, AuditOperationType auditOperationType); } diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAudit.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAudit.java index fe26c591e755..d97d2533b934 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAudit.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAudit.java @@ -33,7 +33,7 @@ import java.io.Serializable; import java.util.Date; import java.util.Objects; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.common.DxfNamespaces; /** @@ -55,7 +55,7 @@ public class TrackedEntityAudit implements Serializable { private String accessedBy; - private ChangeLogType auditType; + private AuditOperationType auditType; // ------------------------------------------------------------------------- // Constructors @@ -63,7 +63,7 @@ public class TrackedEntityAudit implements Serializable { public TrackedEntityAudit() {} - public TrackedEntityAudit(String trackedEntity, String accessedBy, ChangeLogType auditType) { + public TrackedEntityAudit(String trackedEntity, String accessedBy, AuditOperationType auditType) { this.trackedEntity = trackedEntity; this.accessedBy = accessedBy; this.created = new Date(); @@ -75,8 +75,8 @@ public TrackedEntityAudit( String comment, Date created, String accessedBy, - ChangeLogType changeLogType) { - this(trackedEntity, accessedBy, changeLogType); + AuditOperationType auditOperationType) { + this(trackedEntity, accessedBy, auditOperationType); this.comment = comment; this.created = created; } @@ -159,11 +159,11 @@ public void setAccessedBy(String accessedBy) { @JsonProperty @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public ChangeLogType getAuditType() { + public AuditOperationType getAuditType() { return auditType; } - public void setAuditType(ChangeLogType auditType) { + public void setAuditType(AuditOperationType auditType) { this.auditType = auditType; } } diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAuditQueryParams.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAuditQueryParams.java index c06962766b81..e05f52ee7cb5 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAuditQueryParams.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAuditQueryParams.java @@ -32,7 +32,7 @@ import java.util.List; import lombok.Data; import lombok.experimental.Accessors; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.common.Pager; /** @@ -45,7 +45,7 @@ public class TrackedEntityAuditQueryParams { private List users = new ArrayList<>(); - private List auditTypes = new ArrayList<>(); + private List auditTypes = new ArrayList<>(); private Date startDate = null; diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/DataElementMergeService.java b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/DataElementMergeService.java index 1e6b29f801d9..af91e8c5dac4 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/DataElementMergeService.java +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/DataElementMergeService.java @@ -169,7 +169,7 @@ private void initMergeHandlers() { auditMergeHandlers = ImmutableList.builder() - .add(trackerMergeHandler::handleTrackedEntityDataValueChangelog) + .add(trackerMergeHandler::handleEventChangeLogs) .add(dataDataElementMergeHandler::handleDataValueAuditDataElement) .build(); diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/handler/TrackerDataElementMergeHandler.java b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/handler/TrackerDataElementMergeHandler.java index 986dff017c60..f8ab8f8ab623 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/handler/TrackerDataElementMergeHandler.java +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/java/org/hisp/dhis/merge/dataelement/handler/TrackerDataElementMergeHandler.java @@ -57,7 +57,6 @@ import org.hisp.dhis.programrule.ProgramRuleVariableStore; import org.hisp.dhis.tracker.export.event.EventChangeLog; import org.hisp.dhis.tracker.export.event.EventChangeLogService; -import org.hisp.dhis.tracker.export.event.TrackedEntityDataValueChangeLog; import org.springframework.stereotype.Component; /** @@ -275,14 +274,13 @@ private void setLastUpdatedAsTargetAndRemoveRemaining( } /** - * Method handling {@link TrackedEntityDataValueChangeLog}s and {@link EventChangeLog}s. Both of - * them will either be deleted or left as is, based on whether the source {@link DataElement}s are - * being deleted or not. + * Method handling {@link EventChangeLog}s. They will either be deleted or left as is, based on + * whether the source {@link DataElement}s are being deleted or not. * * @param sources source {@link DataElement}s used to retrieve {@link DataValueAudit}s * @param mergeRequest merge request */ - public void handleTrackedEntityDataValueChangelog( + public void handleEventChangeLogs( @Nonnull List sources, @Nonnull MergeRequest mergeRequest) { if (mergeRequest.isDeleteSources()) { log.info("Deleting source event change log records as source DataElements are being deleted"); diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks.yaml b/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks.yaml index a316fe406c47..209893b659a8 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks.yaml +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks.yaml @@ -84,3 +84,4 @@ checks: - users/user_roles_no_authorities.yaml - users/user_roles_with_no_users.yaml - users/users_with_invalid_usernames.yaml + - file_resources/file_resources_no_icon.yaml diff --git a/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks/file_resources/file_resources_no_icon.yaml b/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks/file_resources/file_resources_no_icon.yaml new file mode 100644 index 000000000000..6164d816562e --- /dev/null +++ b/dhis-2/dhis-services/dhis-service-administration/src/main/resources/data-integrity-checks/file_resources/file_resources_no_icon.yaml @@ -0,0 +1,49 @@ +# 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. +# +--- +name: file_resources_no_icon +description: File resources of type ICON that have no entry in the icon table +section: File resources +section_order: 1 +summary_sql: >- + SELECT count(*) FROM fileresource f + WHERE domain = 'ICON' + AND NOT EXISTS (SELECT 1 FROM icon i WHERE i.fileresourceid = f.fileresourceid); +details_sql: > + SELECT f.uid, f.name as name, f.storagekey as comment FROM fileresource f + WHERE domain = 'ICON' + AND NOT EXISTS (SELECT 1 FROM icon i WHERE i.fileresourceid = f.fileresourceid); +details_id_type: fileResources +severity: SEVERE +introduction: > + A file resource of type ICON should always have a corresponding icon entry. +recommendation: > + If the missing icon belongs to a default (system) icon delete the file resource manually. + The icon will be recreated automatically. + If the missing icon is a custom (user provided) icon there are two options: + 1. repair the icon by manually creating the icon entry linked to the existing file resource + 2. discard the icon completely by deleting the file resource manually (image can not be recovered) \ No newline at end of file diff --git a/dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/dataintegrity/DataIntegrityYamlReaderTest.java b/dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/dataintegrity/DataIntegrityYamlReaderTest.java index 1e73189444b8..77fb67fdd3ba 100644 --- a/dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/dataintegrity/DataIntegrityYamlReaderTest.java +++ b/dhis-2/dhis-services/dhis-service-administration/src/test/java/org/hisp/dhis/dataintegrity/DataIntegrityYamlReaderTest.java @@ -57,7 +57,7 @@ void testReadDataIntegrityYaml() { List checks = new ArrayList<>(); readYaml(checks, "data-integrity-checks.yaml", "data-integrity-checks", CLASS_PATH); - assertEquals(85, checks.size()); + assertEquals(86, checks.size()); // Names should be unique List allNames = checks.stream().map(DataIntegrityCheck::getName).toList(); diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/AbstractEventJdbcTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/AbstractEventJdbcTableManager.java index 9392bfc49806..8a98bd7bb0b0 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/AbstractEventJdbcTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/AbstractEventJdbcTableManager.java @@ -28,7 +28,6 @@ package org.hisp.dhis.analytics.table; import static org.hisp.dhis.analytics.table.model.Skip.SKIP; -import static org.hisp.dhis.analytics.util.AnalyticsUtils.getClosingParentheses; import static org.hisp.dhis.analytics.util.AnalyticsUtils.getColumnType; import static org.hisp.dhis.db.model.DataType.GEOMETRY; import static org.hisp.dhis.db.model.DataType.TEXT; @@ -190,7 +189,7 @@ protected void populateTableInternal(AnalyticsTablePartition partition, String f protected List getColumnForAttribute(TrackedEntityAttribute attribute) { List columns = new ArrayList<>(); - String valueColumn = String.format("%s.%s", quote(attribute.getUid()), "value"); + String valueColumn = getValueColumn(attribute); DataType dataType = getColumnType(attribute.getValueType(), isSpatialSupport()); String selectExpression = getColumnExpression(attribute.getValueType(), valueColumn); Skip skipIndex = skipIndex(attribute.getValueType(), attribute.hasOptionSet()); @@ -222,31 +221,23 @@ private List getColumnForOrgUnitAttribute( Validate.isTrue(attribute.getValueType().isOrganisationUnit()); List columns = new ArrayList<>(); - String fromClause = - qualifyVariables("from ${organisationunit} ou where ou.uid = (select value"); - if (isSpatialSupport()) { - String selectExpression = "ou.geometry " + fromClause; - String ouGeoSql = getSelectSubquery(attribute, selectExpression); columns.add( AnalyticsTableColumn.builder() .name((attribute.getUid() + OU_GEOMETRY_COL_SUFFIX)) .dimensionType(AnalyticsDimensionType.DYNAMIC) .dataType(GEOMETRY) - .selectExpression(ouGeoSql) + .selectExpression(getOrgUnitSelectSubquery(attribute, "geometry")) .indexType(IndexType.GIST) .build()); } - String selectExpression = "ou.name " + fromClause; - String ouNameSql = getSelectSubquery(attribute, selectExpression); - columns.add( AnalyticsTableColumn.builder() .name((attribute.getUid() + OU_NAME_COL_SUFFIX)) .dimensionType(AnalyticsDimensionType.DYNAMIC) .dataType(TEXT) - .selectExpression(ouNameSql) + .selectExpression(getOrgUnitSelectSubquery(attribute, "name")) .skipIndex(SKIP) .build()); @@ -254,24 +245,37 @@ private List getColumnForOrgUnitAttribute( } /** - * The select subquery statement. + * Returns the value column with alias. * * @param attribute the {@link TrackedEntityAttribute}. - * @param selectExpression the select expression. - * @return a select statement. + * @return the vlaue column with alias. */ - private String getSelectSubquery(TrackedEntityAttribute attribute, String selectExpression) { - return replaceQualify( + private String getValueColumn(TrackedEntityAttribute attribute) { + return String.format("%s.%s", quote(attribute.getUid()), "value"); + } + + /** + * Returns a org unit select query. + * + * @param attribute the {@link TrackedEntityAttribute}. + * @param column the column name. + * @return an org unit select query. + */ + private String getOrgUnitSelectSubquery(TrackedEntityAttribute attribute, String column) { + String format = """ - (select ${selectExpression} from ${trackedentityattributevalue} \ - where trackedentityid=en.trackedentityid \ - and trackedentityattributeid=${attributeId})\ - ${closingParentheses} as ${attributeUid}""", + (select ou.${column} from ${organisationunit} ou \ + where ou.uid = ${columnExpression}) as ${alias}"""; + String valueColumn = getValueColumn(attribute); + String columnExpression = getColumnExpression(attribute.getValueType(), valueColumn); + String alias = quote(attribute.getUid()); + + return replaceQualify( + format, Map.of( - "selectExpression", selectExpression, - "attributeId", String.valueOf(attribute.getId()), - "closingParentheses", getClosingParentheses(selectExpression), - "attributeUid", quote(attribute.getUid()))); + "column", column, + "columnExpression", columnExpression, + "alias", alias)); } /** diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java index 359bba2ce1d2..31d587e51392 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java @@ -340,38 +340,33 @@ private void populateTable( StringBuilder sql = new StringBuilder(replace("insert into ${tableName} (", Map.of("tableName", tableName))); - List dimensions = partition.getMasterTable().getDimensionColumns(); List columns = partition.getMasterTable().getAnalyticsTableColumns(); + List dimensions = partition.getMasterTable().getDimensionColumns(); - for (AnalyticsTableColumn col : columns) { - sql.append(quote(col.getName()) + ","); - } - - sql = TextUtils.removeLastComma(sql).append(") select "); - - for (AnalyticsTableColumn col : dimensions) { - sql.append(col.getSelectExpression() + ","); - } + sql.append(toCommaSeparated(columns, col -> quote(col.getName()))); + sql.append(") select "); + sql.append(toCommaSeparated(dimensions, AnalyticsTableColumn::getSelectExpression)); + sql.append(","); sql.append( replaceQualify( """ - ${approvalSelectExpression} \ - as approvallevel, \ - ${valueExpression} * ps.daysno as daysxvalue, \ - ps.daysno as daysno, \ - ${valueExpression} as value, \ - ${textValueExpression} as textvalue \ - from ${datavalue} dv \ - inner join analytics_rs_periodstructure ps on dv.periodid=ps.periodid \ - inner join analytics_rs_dataelementstructure des on dv.dataelementid=des.dataelementid \ - inner join analytics_rs_dataelementgroupsetstructure degs on dv.dataelementid=degs.dataelementid \ - inner join analytics_rs_orgunitstructure ous on dv.sourceid=ous.organisationunitid \ - inner join analytics_rs_organisationunitgroupsetstructure ougs on dv.sourceid=ougs.organisationunitid \ - inner join analytics_rs_categorystructure dcs on dv.categoryoptioncomboid=dcs.categoryoptioncomboid \ - inner join analytics_rs_categorystructure acs on dv.attributeoptioncomboid=acs.categoryoptioncomboid \ - inner join analytics_rs_categoryoptioncomboname aon on dv.attributeoptioncomboid=aon.categoryoptioncomboid \ - inner join analytics_rs_categoryoptioncomboname con on dv.categoryoptioncomboid=con.categoryoptioncomboid\s""", + ${approvalSelectExpression} \ + as approvallevel, \ + ${valueExpression} * ps.daysno as daysxvalue, \ + ps.daysno as daysno, \ + ${valueExpression} as value, \ + ${textValueExpression} as textvalue \ + from ${datavalue} dv \ + inner join analytics_rs_periodstructure ps on dv.periodid=ps.periodid \ + inner join analytics_rs_dataelementstructure des on dv.dataelementid=des.dataelementid \ + inner join analytics_rs_dataelementgroupsetstructure degs on dv.dataelementid=degs.dataelementid \ + inner join analytics_rs_orgunitstructure ous on dv.sourceid=ous.organisationunitid \ + inner join analytics_rs_organisationunitgroupsetstructure ougs on dv.sourceid=ougs.organisationunitid \ + inner join analytics_rs_categorystructure dcs on dv.categoryoptioncomboid=dcs.categoryoptioncomboid \ + inner join analytics_rs_categorystructure acs on dv.attributeoptioncomboid=acs.categoryoptioncomboid \ + inner join analytics_rs_categoryoptioncomboname aon on dv.attributeoptioncomboid=aon.categoryoptioncomboid \ + inner join analytics_rs_categoryoptioncomboname con on dv.categoryoptioncomboid=con.categoryoptioncomboid\s""", Map.of( "approvalSelectExpression", approvalSelectExpression, "valueExpression", valueExpression, diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTableManager.java index fe98336a13f9..ba1d569a99b7 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTableManager.java @@ -57,7 +57,6 @@ import org.hisp.dhis.analytics.table.setting.AnalyticsTableSettings; import org.hisp.dhis.category.CategoryService; import org.hisp.dhis.common.IdentifiableObjectManager; -import org.hisp.dhis.commons.util.TextUtils; import org.hisp.dhis.dataapproval.DataApprovalLevelService; import org.hisp.dhis.db.sql.SqlBuilder; import org.hisp.dhis.organisationunit.OrganisationUnitService; @@ -151,11 +150,11 @@ public boolean hasUpdatedLatestData(Date startDate, Date endDate) { String sql = replaceQualify( """ - select cdr.datasetid \ - from ${completedatasetregistration} cdr \ - where cdr.lastupdated >= '${startDate}' \ - and cdr.lastupdated < '${endDate}' \ - limit 1;""", + select cdr.datasetid \ + from ${completedatasetregistration} cdr \ + where cdr.lastupdated >= '${startDate}' \ + and cdr.lastupdated < '${endDate}' \ + limit 1;""", Map.of("startDate", toLongDate(startDate), "endDate", toLongDate(endDate))); return !jdbcTemplate.queryForList(sql).isEmpty(); @@ -196,24 +195,14 @@ public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTableParti String tableName = partition.getName(); String partitionClause = getPartitionClause(partition); - String sql = "insert into " + tableName + " ("; - List columns = partition.getMasterTable().getAnalyticsTableColumns(); - for (AnalyticsTableColumn col : columns) { - sql += quote(col.getName()) + ","; - } - - sql = TextUtils.removeLastComma(sql) + ") select "; - - for (AnalyticsTableColumn col : columns) { - sql += col.getSelectExpression() + ","; - } - - sql = TextUtils.removeLastComma(sql) + " "; - + String sql = "insert into " + tableName + " ("; + sql += toCommaSeparated(columns, col -> quote(col.getName())); + sql += ") select "; + sql += toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression); + sql += " "; // Database legacy fix - sql = sql.replace("organisationunitid", "sourceid"); sql += diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTargetTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTargetTableManager.java index 4b74d8ccee2a..ed32291a7083 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTargetTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcCompletenessTargetTableManager.java @@ -48,7 +48,6 @@ import org.hisp.dhis.analytics.table.setting.AnalyticsTableSettings; import org.hisp.dhis.category.CategoryService; import org.hisp.dhis.common.IdentifiableObjectManager; -import org.hisp.dhis.commons.util.TextUtils; import org.hisp.dhis.dataapproval.DataApprovalLevelService; import org.hisp.dhis.db.model.Logged; import org.hisp.dhis.db.sql.SqlBuilder; @@ -159,21 +158,13 @@ protected List getPartitionChecks(Integer year, Date endDate) { public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTablePartition partition) { String tableName = partition.getName(); - String sql = "insert into " + tableName + " ("; - List columns = partition.getMasterTable().getAnalyticsTableColumns(); - for (AnalyticsTableColumn col : columns) { - sql += quote(col.getName()) + ","; - } - - sql = TextUtils.removeLastComma(sql) + ") select "; - - for (AnalyticsTableColumn col : columns) { - sql += col.getSelectExpression() + ","; - } - - sql = TextUtils.removeLastComma(sql) + " "; + String sql = "insert into " + tableName + " ("; + sql += toCommaSeparated(columns, col -> quote(col.getName())); + sql += ") select "; + sql += toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression); + sql += " "; sql += qualifyVariables( diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManager.java index 172745e793d3..a57db9c8e68c 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManager.java @@ -150,7 +150,7 @@ left join analytics_rs_dateperiodstructure dps on cast(en.enrollmentdate as date left join analytics_rs_orgunitstructure ous on en.organisationunitid=ous.organisationunitid \ left join analytics_rs_organisationunitgroupsetstructure ougs on en.organisationunitid=ougs.organisationunitid \ ${attributeJoinClause}\ - where pr.programid=${programId} \ + where pr.programid = ${programId} \ and en.organisationunitid is not null \ and (ougs.startdate is null or dps.monthstartdate=ougs.startdate) \ and en.lastupdated <= '${startTime}' \ diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java index 94c8a2805487..bde55a83d977 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java @@ -346,7 +346,7 @@ left join analytics_rs_dateperiodstructure dps on cast(${eventDateExpression} as inner join analytics_rs_categorystructure acs on ev.attributeoptioncomboid=acs.categoryoptioncomboid \ ${attributeJoinClause}\ where ev.lastupdated < '${startTime}' ${partitionClause} \ - and pr.programid=${programId} \ + and pr.programid = ${programId} \ and ev.organisationunitid is not null \ and (${eventDateExpression}) is not null \ and (ougs.startdate is null or dps.monthstartdate=ougs.startdate) \ @@ -532,7 +532,7 @@ private List getColumnForOrgUnitDataElement(DataElement da .name((dataElement.getUid() + OU_GEOMETRY_COL_SUFFIX)) .dimensionType(AnalyticsDimensionType.DYNAMIC) .dataType(GEOMETRY) - .selectExpression(getOrgUnitSelectSubquery("geometry", dataElement)) + .selectExpression(getOrgUnitSelectSubquery(dataElement, "geometry")) .indexType(IndexType.GIST) .build()); } @@ -542,7 +542,7 @@ private List getColumnForOrgUnitDataElement(DataElement da .name((dataElement.getUid() + OU_NAME_COL_SUFFIX)) .dimensionType(AnalyticsDimensionType.DYNAMIC) .dataType(TEXT) - .selectExpression(getOrgUnitSelectSubquery("name", dataElement)) + .selectExpression(getOrgUnitSelectSubquery(dataElement, "name")) .skipIndex(SKIP) .build()); @@ -552,11 +552,11 @@ private List getColumnForOrgUnitDataElement(DataElement da /** * Returns a org unit select query. * - * @param column the column name. * @param dataElement the {@link DataElement}. + * @param column the column name. * @return an org unit select query. */ - private String getOrgUnitSelectSubquery(String column, DataElement dataElement) { + private String getOrgUnitSelectSubquery(DataElement dataElement, String column) { String format = """ (select ou.${column} from ${organisationunit} ou \ diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOrgUnitTargetTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOrgUnitTargetTableManager.java index 5874ec70477f..9515e9eac449 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOrgUnitTargetTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOrgUnitTargetTableManager.java @@ -49,7 +49,6 @@ import org.hisp.dhis.analytics.table.setting.AnalyticsTableSettings; import org.hisp.dhis.category.CategoryService; import org.hisp.dhis.common.IdentifiableObjectManager; -import org.hisp.dhis.commons.util.TextUtils; import org.hisp.dhis.dataapproval.DataApprovalLevelService; import org.hisp.dhis.db.model.Logged; import org.hisp.dhis.db.sql.SqlBuilder; @@ -134,21 +133,13 @@ protected List getPartitionChecks(Integer year, Date endDate) { public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTablePartition partition) { String tableName = partition.getName(); - String sql = replace("insert into ${tableName} (", Map.of("tableName", quote(tableName))); - List columns = partition.getMasterTable().getAnalyticsTableColumns(); - for (AnalyticsTableColumn col : columns) { - sql += quote(col.getName()) + ","; - } - - sql = TextUtils.removeLastComma(sql) + ") select "; - - for (AnalyticsTableColumn col : columns) { - sql += col.getSelectExpression() + ","; - } - - sql = TextUtils.removeLastComma(sql) + " "; + String sql = replace("insert into ${tableName} (", Map.of("tableName", quote(tableName))); + sql += toCommaSeparated(columns, col -> quote(col.getName())); + sql += ") select "; + sql += toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression); + sql += " "; sql += qualifyVariables( diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOwnershipAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOwnershipAnalyticsTableManager.java index 2d3b77847e19..50bf484bddb9 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOwnershipAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcOwnershipAnalyticsTableManager.java @@ -239,15 +239,12 @@ private void populateOwnershipTableInternal(AnalyticsTablePartition partition, S * @return a SQL select query. */ private String getInputSql(Program program) { - StringBuilder sb = new StringBuilder("select "); + List columns = getColumns(); - for (AnalyticsTableColumn col : getColumns()) { - sb.append(col.getSelectExpression()).append(","); - } - - sb.deleteCharAt(sb.length() - 1); // Remove the final ','. + StringBuilder sql = new StringBuilder("select "); + sql.append(toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression)); - sb.append( + sql.append( replaceQualify( """ \sfrom (\ @@ -272,7 +269,7 @@ and exists (\ "historyTableId", HISTORY_TABLE_ID, "trackedEntityOwnTableId", TRACKED_ENTITY_OWN_TABLE_ID, "programId", String.valueOf(program.getId())))); - return sb.toString(); + return sql.toString(); } private Map getRowMap(List columnNames, ResultSet resultSet) diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityAnalyticsTableManager.java index 4a483d156d37..dc0e4030bcf0 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityAnalyticsTableManager.java @@ -34,8 +34,6 @@ import static org.hisp.dhis.analytics.table.JdbcEventAnalyticsTableManager.EXPORTABLE_EVENT_STATUSES; import static org.hisp.dhis.analytics.util.AnalyticsUtils.getColumnType; import static org.hisp.dhis.analytics.util.DisplayNameUtils.getDisplayName; -import static org.hisp.dhis.commons.util.TextUtils.removeLastComma; -import static org.hisp.dhis.commons.util.TextUtils.replace; import static org.hisp.dhis.db.model.DataType.BOOLEAN; import static org.hisp.dhis.db.model.DataType.CHARACTER_11; import static org.hisp.dhis.db.model.DataType.DOUBLE; @@ -65,7 +63,6 @@ import org.hisp.dhis.analytics.table.setting.AnalyticsTableSettings; import org.hisp.dhis.category.CategoryService; import org.hisp.dhis.common.IdentifiableObjectManager; -import org.hisp.dhis.common.ValueType; import org.hisp.dhis.dataapproval.DataApprovalLevelService; import org.hisp.dhis.db.model.IndexType; import org.hisp.dhis.db.model.Logged; @@ -85,7 +82,7 @@ import org.springframework.transaction.annotation.Transactional; @Component("org.hisp.dhis.analytics.TrackedEntityAnalyticsTableManager") -public class JdbcTrackedEntityAnalyticsTableManager extends AbstractJdbcTableManager { +public class JdbcTrackedEntityAnalyticsTableManager extends AbstractEventJdbcTableManager { private static final String PROGRAMS_BY_TET_KEY = "programsByTetUid"; private static final String ALL_NON_CONFIDENTIAL_TET_ATTRIBUTES = @@ -215,7 +212,7 @@ private List getColumns( .name(tea.getUid()) .dataType(getColumnType(tea.getValueType(), isSpatialSupport())) .selectExpression( - castBasedOnType(tea.getValueType(), quote(tea.getUid()) + ".value")) + getColumnExpression(tea.getValueType(), quote(tea.getUid()) + ".value")) .build()) .toList()); @@ -242,41 +239,6 @@ private Stream getAllTrackedEntityAttributes( return getAllTrackedEntityAttributesByEntityType(trackedEntityType); } - /** - * Returns the select clause, potentially with a cast statement, based on the given value type. - * - * @param valueType the value type to represent as database column type. - */ - private String castBasedOnType(ValueType valueType, String columnName) { - if (valueType.isDecimal()) { - - return replace( - " cast(${columnName} as ${type})", - Map.of("columnName", columnName, "type", sqlBuilder.dataTypeDouble())); - } - if (valueType.isInteger()) { - return replace(" cast(${columnName} as bigint)", Map.of("columnName", columnName)); - } - if (valueType.isBoolean()) { - return replace( - " case when ${columnName} = 'true' then 1 when ${columnName} = 'false' then 0 end ", - Map.of("columnName", columnName)); - } - if (valueType.isDate()) { - return replace( - " cast(${columnName} as ${type})", - Map.of("columnName", columnName, "type", sqlBuilder.dataTypeTimestamp())); - } - if (valueType.isGeo() && isSpatialSupport() && sqlBuilder.supportsGeospatialData()) { - return replace( - """ - \s ST_GeomFromGeoJSON('{"type":"Point", "coordinates":' || (${columnName}) || ', - "crs":{"type":"name", "properties":{"name":"EPSG:4326"}}}')""", - Map.of("columnName", columnName)); - } - return columnName; - } - /** * Returns all {@link TrackedEntityAttribute} for the given {@link TrackedEntityType} and * programs. @@ -332,27 +294,19 @@ public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTableParti List columns = partition.getMasterTable().getAnalyticsTableColumns(); StringBuilder sql = new StringBuilder("insert into " + tableName + " ("); - - for (AnalyticsTableColumn col : columns) { - sql.append(quote(col.getName()) + ","); - } - - removeLastComma(sql).append(") select "); - - for (AnalyticsTableColumn col : columns) { - sql.append(col.getSelectExpression() + ","); - } + sql.append(toCommaSeparated(columns, col -> quote(col.getName()))); + sql.append(") select "); + sql.append(toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression)); TrackedEntityType trackedEntityType = partition.getMasterTable().getTrackedEntityType(); - removeLastComma(sql) - .append( - replaceQualify( - """ - \sfrom ${trackedentity} te \ - left join analytics_rs_orgunitstructure ous on te.organisationunitid=ous.organisationunitid \ - left join analytics_rs_organisationunitgroupsetstructure ougs on te.organisationunitid=ougs.organisationunitid""", - Map.of())); + sql.append( + replaceQualify( + """ + \sfrom ${trackedentity} te \ + left join analytics_rs_orgunitstructure ous on te.organisationunitid=ous.organisationunitid \ + left join analytics_rs_organisationunitgroupsetstructure ougs on te.organisationunitid=ougs.organisationunitid""", + Map.of())); ((List) params.getExtraParam(trackedEntityType.getUid(), ALL_NON_CONFIDENTIAL_TET_ATTRIBUTES)) diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEnrollmentsAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEnrollmentsAnalyticsTableManager.java index 70428872148d..31d7c936eda9 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEnrollmentsAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEnrollmentsAnalyticsTableManager.java @@ -31,7 +31,6 @@ import static java.lang.String.valueOf; import static org.hisp.dhis.analytics.AnalyticsTableType.TRACKED_ENTITY_INSTANCE_ENROLLMENTS; import static org.hisp.dhis.analytics.table.JdbcEventAnalyticsTableManager.EXPORTABLE_EVENT_STATUSES; -import static org.hisp.dhis.commons.util.TextUtils.removeLastComma; import static org.hisp.dhis.db.model.DataType.CHARACTER_11; import static org.hisp.dhis.db.model.DataType.DOUBLE; import static org.hisp.dhis.db.model.DataType.GEOMETRY; @@ -115,30 +114,6 @@ public class JdbcTrackedEntityEnrollmentsAnalyticsTableManager extends AbstractJ .dataType(VARCHAR_50) .selectExpression("en.status") .build(), - AnalyticsTableColumn.builder() - .name("uidlevel1") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel1") - .build(), - AnalyticsTableColumn.builder() - .name("uidlevel2") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel2") - .build(), - AnalyticsTableColumn.builder() - .name("uidlevel3") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel3") - .build(), - AnalyticsTableColumn.builder() - .name("uidlevel4") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel4") - .build(), AnalyticsTableColumn.builder() .name("ou") .dataType(CHARACTER_11) @@ -225,6 +200,7 @@ private List getColumns() { List columns = new ArrayList<>(); columns.addAll(getFixedCols()); columns.add(getOrganisationUnitNameHierarchyColumn()); + columns.addAll(getOrganisationUnitLevelColumns()); if (sqlBuilder.supportsDeclarativePartitioning()) { columns.add(getPartitionColumn()); } @@ -245,41 +221,33 @@ protected List getPartitionChecks(Integer year, Date endDate) { @Override public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTablePartition partition) { String tableName = partition.getName(); + long tetId = partition.getMasterTable().getTrackedEntityType().getId(); List columns = partition.getMasterTable().getAnalyticsTableColumns(); StringBuilder sql = new StringBuilder("insert into " + tableName + " ("); + sql.append(toCommaSeparated(columns, col -> quote(col.getName()))); + sql.append(") select "); + sql.append(toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression)); - for (AnalyticsTableColumn col : columns) { - sql.append(quote(col.getName()) + ","); - } - - removeLastComma(sql).append(") select "); - - for (AnalyticsTableColumn col : columns) { - sql.append(col.getSelectExpression() + ","); - } - - removeLastComma(sql) - .append( - replaceQualify( - """ - \sfrom ${enrollment} en \ - inner join ${trackedentity} te on en.trackedentityid=te.trackedentityid \ - and te.deleted = false and te.trackedentitytypeid = ${trackedEntityTypeId} \ - and te.lastupdated < '${startTime}' \ - left join ${program} p on en.programid=p.programid \ - left join analytics_rs_orgunitstructure ous on en.organisationunitid=ous.organisationunitid \ - where exists (select 1 from ${event} ev where ev.deleted = false \ - and ev.enrollmentid = en.enrollmentid \ - and ev.status in (${statuses})) \ - and en.occurreddate is not null \ - and en.deleted = false\s""", - Map.of( - "trackedEntityTypeId", - valueOf(partition.getMasterTable().getTrackedEntityType().getId()), - "startTime", toLongDate(params.getStartTime()), - "statuses", join(",", EXPORTABLE_EVENT_STATUSES)))); + sql.append( + replaceQualify( + """ + \sfrom ${enrollment} en \ + inner join ${trackedentity} te on en.trackedentityid=te.trackedentityid \ + and te.deleted = false and te.trackedentitytypeid = ${trackedEntityTypeId} \ + and te.lastupdated < '${startTime}' \ + left join ${program} p on en.programid=p.programid \ + left join analytics_rs_orgunitstructure ous on en.organisationunitid=ous.organisationunitid \ + where exists (select 1 from ${event} ev where ev.deleted = false \ + and ev.enrollmentid = en.enrollmentid \ + and ev.status in (${statuses})) \ + and en.occurreddate is not null \ + and en.deleted = false\s""", + Map.of( + "trackedEntityTypeId", valueOf(tetId), + "startTime", toLongDate(params.getStartTime()), + "statuses", join(",", EXPORTABLE_EVENT_STATUSES)))); invokeTimeAndLog(sql.toString(), "Populating table: '{}'", tableName); } diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManager.java index a89213becd23..7f9aed298e6a 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManager.java @@ -34,7 +34,6 @@ import static org.hisp.dhis.analytics.table.util.PartitionUtils.getStartDate; import static org.hisp.dhis.commons.util.TextUtils.emptyIfTrue; import static org.hisp.dhis.commons.util.TextUtils.format; -import static org.hisp.dhis.commons.util.TextUtils.removeLastComma; import static org.hisp.dhis.commons.util.TextUtils.replace; import static org.hisp.dhis.db.model.DataType.CHARACTER_11; import static org.hisp.dhis.db.model.DataType.DOUBLE; @@ -143,30 +142,6 @@ public class JdbcTrackedEntityEventsAnalyticsTableManager extends AbstractJdbcTa .dataType(VARCHAR_50) .selectExpression("ev.status") .build(), - AnalyticsTableColumn.builder() - .name("uidlevel1") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel1") - .build(), - AnalyticsTableColumn.builder() - .name("uidlevel2") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel2") - .build(), - AnalyticsTableColumn.builder() - .name("uidlevel3") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel3") - .build(), - AnalyticsTableColumn.builder() - .name("uidlevel4") - .dataType(CHARACTER_11) - .nullable(NULL) - .selectExpression("ous.uidlevel4") - .build(), AnalyticsTableColumn.builder() .name("ou") .dataType(CHARACTER_11) @@ -367,6 +342,7 @@ private List getColumns() { } columns.add(getOrganisationUnitNameHierarchyColumn()); + columns.addAll(getOrganisationUnitLevelColumns()); return columns; } @@ -386,41 +362,35 @@ protected List getPartitionChecks(Integer year, Date endDate) { public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTablePartition partition) { AnalyticsTable masterTable = partition.getMasterTable(); String tableName = partition.getName(); + long tetId = masterTable.getTrackedEntityType().getId(); List columns = partition.getMasterTable().getAnalyticsTableColumns(); String partitionClause = sqlBuilder.supportsDeclarativePartitioning() ? "" : getPartitionClause(partition); StringBuilder sql = new StringBuilder("insert into " + tableName + " ("); + sql.append(toCommaSeparated(columns, col -> quote(col.getName()))); + sql.append(") select distinct "); + sql.append(toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression)); + sql.append(" "); - for (AnalyticsTableColumn col : columns) { - sql.append(quote(col.getName()) + ","); - } - - removeLastComma(sql).append(") select distinct "); - - for (AnalyticsTableColumn col : columns) { - sql.append(col.getSelectExpression() + ","); - } - - removeLastComma(sql) - .append( - replaceQualify( - """ - \s from ${event} ev \ - inner join ${enrollment} en on en.enrollmentid=ev.enrollmentid and en.deleted = false \ - inner join ${trackedentity} te on te.trackedentityid=en.trackedentityid \ - and te.deleted = false and te.trackedentitytypeid = ${tetId} and te.lastupdated < '${startTime}' \ - left join ${programstage} ps on ev.programstageid=ps.programstageid \ - left join ${program} p on ps.programid=p.programid \ - left join analytics_rs_orgunitstructure ous on ev.organisationunitid=ous.organisationunitid \ - where ev.status in (${statuses}) \ - ${partitionClause} \ - and ev.deleted = false\s""", - Map.of( - "tetId", String.valueOf(masterTable.getTrackedEntityType().getId()), - "startTime", toLongDate(params.getStartTime()), - "statuses", join(",", EXPORTABLE_EVENT_STATUSES), - "partitionClause", partitionClause))); + sql.append( + replaceQualify( + """ + from ${event} ev \ + inner join ${enrollment} en on en.enrollmentid=ev.enrollmentid and en.deleted = false \ + inner join ${trackedentity} te on te.trackedentityid=en.trackedentityid \ + and te.deleted = false and te.trackedentitytypeid = ${tetId} and te.lastupdated < '${startTime}' \ + left join ${programstage} ps on ev.programstageid=ps.programstageid \ + left join ${program} p on ps.programid=p.programid \ + left join analytics_rs_orgunitstructure ous on ev.organisationunitid=ous.organisationunitid \ + where ev.status in (${statuses}) \ + ${partitionClause} \ + and ev.deleted = false\s""", + Map.of( + "tetId", String.valueOf(tetId), + "startTime", toLongDate(params.getStartTime()), + "statuses", join(",", EXPORTABLE_EVENT_STATUSES), + "partitionClause", partitionClause))); invokeTimeAndLog(sql.toString(), "Populating table: '{}'", tableName); } diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcValidationResultTableManager.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcValidationResultTableManager.java index 26614fdc3c12..e6409edcd11f 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcValidationResultTableManager.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcValidationResultTableManager.java @@ -30,7 +30,6 @@ import static org.hisp.dhis.analytics.table.model.AnalyticsValueType.FACT; import static org.hisp.dhis.commons.util.TextUtils.emptyIfTrue; import static org.hisp.dhis.commons.util.TextUtils.format; -import static org.hisp.dhis.commons.util.TextUtils.removeLastComma; import static org.hisp.dhis.db.model.DataType.CHARACTER_11; import static org.hisp.dhis.db.model.DataType.DATE; import static org.hisp.dhis.db.model.DataType.INTEGER; @@ -164,21 +163,13 @@ public void populateTable(AnalyticsTableUpdateParams params, AnalyticsTableParti String tableName = partition.getName(); String partitionClause = getPartitionClause(partition); - String sql = "insert into " + tableName + " ("; - List columns = partition.getMasterTable().getAnalyticsTableColumns(); - for (AnalyticsTableColumn col : columns) { - sql += quote(col.getName()) + ","; - } - - sql = removeLastComma(sql) + ") select "; - - for (AnalyticsTableColumn col : columns) { - sql += col.getSelectExpression() + ","; - } - - sql = removeLastComma(sql) + " "; + String sql = "insert into " + tableName + " ("; + sql += toCommaSeparated(columns, col -> quote(col.getName())); + sql += ") select "; + sql += toCommaSeparated(columns, AnalyticsTableColumn::getSelectExpression); + sql += " "; // Database legacy fix diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/AnalyticsUtils.java b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/AnalyticsUtils.java index cf73c25f349d..b61b7a82bbaa 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/AnalyticsUtils.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/util/AnalyticsUtils.java @@ -27,7 +27,6 @@ */ package org.hisp.dhis.analytics.util; -import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.hisp.dhis.common.DataDimensionItem.DATA_DIM_TYPE_CLASS_MAP; import static org.hisp.dhis.common.DimensionalObject.ATTRIBUTEOPTIONCOMBO_DIM_ID; import static org.hisp.dhis.common.DimensionalObject.CATEGORYOPTIONCOMBO_DIM_ID; @@ -1202,33 +1201,4 @@ public static String replaceStringBetween( Matcher matcher = pattern.matcher(original); return matcher.replaceAll(startToken + replacement + endToken); } - - /** - * Returns a string containing closing parenthesis. The number of parenthesis is based on the - * number of missing closing parenthesis in the argument string. - * - *

Example: - * - *

{@code} input: "((( ))" -> output: ")" {@code} - * - * @param str a string. - * @return a String containing 0 or more "closing" parenthesis - */ - public static String getClosingParentheses(String str) { - if (StringUtils.isEmpty(str)) { - return EMPTY; - } - - int open = 0; - - for (int i = 0; i < str.length(); i++) { - if (str.charAt(i) == '(') { - open++; - } else if ((str.charAt(i) == ')') && open >= 1) { - open--; - } - } - - return StringUtils.repeat(")", open); - } } diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/AnalyticsTableServiceTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/AnalyticsTableServiceTest.java index 91389524f5de..3322599ee643 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/AnalyticsTableServiceTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/AnalyticsTableServiceTest.java @@ -30,7 +30,6 @@ import static org.hisp.dhis.db.model.DataType.DOUBLE; import static org.hisp.dhis.db.model.DataType.TEXT; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; import java.util.List; @@ -43,7 +42,6 @@ import org.hisp.dhis.setting.SystemSettings; import org.hisp.dhis.setting.SystemSettingsProvider; import org.joda.time.DateTime; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -63,11 +61,6 @@ class AnalyticsTableServiceTest { @InjectMocks private DefaultAnalyticsTableService tableService; - @BeforeEach - void setUp() { - lenient().when(settingsProvider.getCurrentSettings()).thenReturn(settings); - } - @Test void testGetTablePartitions() { when(sqlBuilder.supportsDeclarativePartitioning()).thenReturn(false); @@ -104,6 +97,7 @@ void testGetTablePartitions() { @Test void testGetParallelJobsA() { + when(settingsProvider.getCurrentSettings()).thenReturn(settings); when(settings.getParallelJobsInAnalyticsTableExport()).thenReturn(1); assertEquals(1, tableService.getParallelJobs()); @@ -111,6 +105,7 @@ void testGetParallelJobsA() { @Test void testGetParallelJobsB() { + when(settingsProvider.getCurrentSettings()).thenReturn(settings); when(settings.getParallelJobsInAnalyticsTableExport()).thenReturn(-1); when(settings.getDatabaseServerCpus()).thenReturn(8); diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManagerTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManagerTest.java index 76a6eb4bd460..7c968b08511a 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManagerTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManagerTest.java @@ -35,7 +35,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,6 +67,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.Spy; @@ -82,38 +82,38 @@ @MockitoSettings(strictness = Strictness.LENIENT) @ExtendWith(MockitoExtension.class) class JdbcAnalyticsTableManagerTest { + @Mock private IdentifiableObjectManager idObjectManager; + + @Mock private OrganisationUnitService organisationUnitService; + + @Mock private CategoryService categoryService; + @Mock private SystemSettingsProvider settingsProvider; @Mock private SystemSettings settings; + @Mock private DataApprovalLevelService dataApprovalLevelService; + + @Mock private ResourceTableService resourceTableService; + + @Mock private AnalyticsTableHookService analyticsTableHookService; + + @Mock private PartitionManager partitionManager; + @Mock private JdbcTemplate jdbcTemplate; @Mock private AnalyticsTableSettings analyticsTableSettings; @Mock private PeriodDataProvider periodDataProvider; - @Spy private final SqlBuilder sqlBuilder = new PostgreSqlBuilder(); + @Spy private SqlBuilder sqlBuilder = new PostgreSqlBuilder(); - private JdbcAnalyticsTableManager subject; + @InjectMocks private JdbcAnalyticsTableManager subject; @BeforeEach public void setUp() { when(settingsProvider.getCurrentSettings()).thenReturn(settings); when(settings.getLastSuccessfulResourceTablesUpdate()).thenReturn(new Date(0L)); - subject = - new JdbcAnalyticsTableManager( - mock(IdentifiableObjectManager.class), - mock(OrganisationUnitService.class), - mock(CategoryService.class), - settingsProvider, - mock(DataApprovalLevelService.class), - mock(ResourceTableService.class), - mock(AnalyticsTableHookService.class), - mock(PartitionManager.class), - jdbcTemplate, - analyticsTableSettings, - periodDataProvider, - sqlBuilder); } @Test diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManagerTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManagerTest.java index f2f2d642cf42..4d7463b8fb6e 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManagerTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEnrollmentAnalyticsTableManagerTest.java @@ -36,7 +36,6 @@ import static org.hisp.dhis.test.TestBase.createTrackedEntityAttribute; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,7 +67,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.jdbc.core.JdbcTemplate; @@ -79,37 +80,38 @@ class JdbcEnrollmentAnalyticsTableManagerTest { @Mock private IdentifiableObjectManager idObjectManager; + @Mock private OrganisationUnitService organisationUnitService; + + @Mock private CategoryService categoryService; + + @Mock private SystemSettingsProvider settingsProvider; + + @Mock private SystemSettings settings; + + @Mock private DataApprovalLevelService dataApprovalLevelService; + + @Mock private ResourceTableService resourceTableService; + + @Mock private AnalyticsTableHookService analyticsTableHookService; + + @Mock private PartitionManager partitionManager; + @Mock private JdbcTemplate jdbcTemplate; @Mock private AnalyticsTableSettings analyticsTableSettings; @Mock private PeriodDataProvider periodDataProvider; - private final SqlBuilder sqlBuilder = new PostgreSqlBuilder(); + @Spy private SqlBuilder sqlBuilder = new PostgreSqlBuilder(); - private JdbcEnrollmentAnalyticsTableManager subject; + @InjectMocks private JdbcEnrollmentAnalyticsTableManager subject; private static final Date START_TIME = new DateTime(2019, 8, 1, 0, 0).toDate(); @BeforeEach public void setUp() { when(analyticsTableSettings.isSpatialSupport()).thenReturn(true); - SystemSettingsProvider settingsProvider = mock(SystemSettingsProvider.class); lenient().when(settingsProvider.getCurrentSettings()).thenReturn(SystemSettings.of(Map.of())); - subject = - new JdbcEnrollmentAnalyticsTableManager( - idObjectManager, - mock(OrganisationUnitService.class), - mock(CategoryService.class), - settingsProvider, - mock(DataApprovalLevelService.class), - mock(ResourceTableService.class), - mock(AnalyticsTableHookService.class), - mock(PartitionManager.class), - jdbcTemplate, - analyticsTableSettings, - periodDataProvider, - sqlBuilder); } @Test diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManagerTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManagerTest.java index 9a9db09b4f99..15e1eb3b9a6d 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManagerTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManagerTest.java @@ -501,11 +501,17 @@ void verifyGetTableWithTrackedEntityAttribute() { eventdatavalues #>> '{deabcdefghZ, value}' as "deabcdefghZ\""""; String aliasTeaUid = "%s.value"; - String aliasTea1 = - """ - (select %s from "organisationunit" ou where ou.uid = \ - (select value from "trackedentityattributevalue" where trackedentityid=en.trackedentityid \ - and trackedentityattributeid=%d)) as "%s\""""; + String ouGeometryQuery = + String.format( + """ + (select ou.geometry from "organisationunit" ou where ou.uid = %1$s.value) as %1$s""", + quote(tea1.getUid())); + + String ouNameQuery = + String.format( + """ + (select ou.name from "organisationunit" ou where ou.uid = %1$s.value) as %1$s""", + quote(tea1.getUid())); AnalyticsTableUpdateParams params = AnalyticsTableUpdateParams.newBuilder() @@ -535,17 +541,9 @@ void verifyGetTableWithTrackedEntityAttribute() { .addColumn(d1.getUid(), TEXT, toSelectExpression(aliasD1, d1.getUid()), Skip.SKIP) .addColumn(tea1.getUid(), TEXT, String.format(aliasTeaUid, quote(tea1.getUid()))) // Org unit geometry column - .addColumn( - tea1.getUid() + "_geom", - GEOMETRY, - String.format(aliasTea1, "ou.geometry", tea1.getId(), tea1.getUid()), - IndexType.GIST) + .addColumn(tea1.getUid() + "_geom", GEOMETRY, ouGeometryQuery, IndexType.GIST) // Org unit name column - .addColumn( - tea1.getUid() + "_name", - TEXT, - String.format(aliasTea1, "ou.name", tea1.getId(), tea1.getUid()), - Skip.SKIP) + .addColumn(tea1.getUid() + "_name", TEXT, ouNameQuery, Skip.SKIP) .withDefaultColumns(EventAnalyticsColumn.getColumns(sqlBuilder)) .build() .verify(); @@ -643,15 +641,20 @@ void verifyTeiTypeOrgUnitFetchesOuNameWhenPopulatingEventAnalyticsTable() { String ouUidQuery = String.format("%s.value", quote(tea.getUid())); + String ouGeometryQuery = + String.format( + """ + (select ou.geometry from "organisationunit" ou where ou.uid = %1$s.value) as %1$s""", + quote(tea.getUid())); + String ouNameQuery = String.format( """ - (select ou.name from "organisationunit" ou where ou.uid = \ - (select value from "trackedentityattributevalue" where trackedentityid=en.trackedentityid and \ - trackedentityattributeid=9999)) as %s""", + (select ou.name from "organisationunit" ou where ou.uid = %1$s.value) as %1$s""", quote(tea.getUid())); assertThat(sql.getValue(), containsString(ouUidQuery)); + assertThat(sql.getValue(), containsString(ouGeometryQuery)); assertThat(sql.getValue(), containsString(ouNameQuery)); } @@ -932,15 +935,20 @@ void verifyTeaTypeOrgUnitFetchesOuNameWhenPopulatingEventAnalyticsTable() { String ouUidQuery = String.format("%s.value", quote(tea.getUid())); + String ouGeometryQuery = + String.format( + """ + (select ou.geometry from "organisationunit" ou where ou.uid = %1$s.value) as %1$s""", + quote(tea.getUid())); + String ouNameQuery = String.format( """ - (select ou.name from "organisationunit" ou where ou.uid = \ - (select value from "trackedentityattributevalue" where trackedentityid=en.trackedentityid \ - and trackedentityattributeid=9999)) as %s""", + (select ou.name from "organisationunit" ou where ou.uid = %1$s.value) as %1$s""", quote(tea.getUid())); assertThat(sql.getValue(), containsString(ouUidQuery)); + assertThat(sql.getValue(), containsString(ouGeometryQuery)); assertThat(sql.getValue(), containsString(ouNameQuery)); } diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManagerTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManagerTest.java index bcc61a915cad..57fce6c172ac 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManagerTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/JdbcTrackedEntityEventsAnalyticsTableManagerTest.java @@ -114,7 +114,7 @@ void testTableName() { } @Test - void testPopulate() { + void testPopulateTable() { TrackedEntityType tet = mock(TrackedEntityType.class); when(tet.getUid()).thenReturn("tetUid"); when(trackedEntityTypeService.getAllTrackedEntityType()).thenReturn(List.of(tet)); @@ -135,46 +135,46 @@ void testPopulate() { String subQuery = """ - (select json_object_agg(l2.keys, l2.datavalue) as value - from ( - select l1.uid, - l1.keys, - json_strip_nulls(json_build_object( - 'value', l1.eventdatavalues -> l1.keys ->> 'value', - 'created', l1.eventdatavalues -> l1.keys ->> 'created', - 'storedBy', l1.eventdatavalues -> l1.keys ->> 'storedBy', - 'lastUpdated', l1.eventdatavalues -> l1.keys ->> 'lastUpdated', - 'providedElsewhere', l1.eventdatavalues -> l1.keys -> 'providedElsewhere', - 'value_name', (select ou.name - from organisationunit ou - where ou.uid = l1.eventdatavalues -> l1.keys ->> 'value'), - 'value_code', (select ou.code - from organisationunit ou - where ou.uid = l1.eventdatavalues -> l1.keys ->> 'value'))) as datavalue - from (select inner_evt.*, jsonb_object_keys(inner_evt.eventdatavalues) keys - from event inner_evt) as l1) as l2 - where l2.uid = ev.uid - group by l2.uid)::jsonb - """; + (select json_object_agg(l2.keys, l2.datavalue) as value + from ( + select l1.uid, + l1.keys, + json_strip_nulls(json_build_object( + 'value', l1.eventdatavalues -> l1.keys ->> 'value', + 'created', l1.eventdatavalues -> l1.keys ->> 'created', + 'storedBy', l1.eventdatavalues -> l1.keys ->> 'storedBy', + 'lastUpdated', l1.eventdatavalues -> l1.keys ->> 'lastUpdated', + 'providedElsewhere', l1.eventdatavalues -> l1.keys -> 'providedElsewhere', + 'value_name', (select ou.name + from organisationunit ou + where ou.uid = l1.eventdatavalues -> l1.keys ->> 'value'), + 'value_code', (select ou.code + from organisationunit ou + where ou.uid = l1.eventdatavalues -> l1.keys ->> 'value'))) as datavalue + from (select inner_evt.*, jsonb_object_keys(inner_evt.eventdatavalues) keys + from event inner_evt) as l1) as l2 + where l2.uid = ev.uid + group by l2.uid)::jsonb + """; String expectedSql = """ - insert into analytics_te_event_tetuid_temp ("trackedentity","program","enrollment","programstage","event","occurreddate","lastupdated","created", - "scheduleddate","status","uidlevel1","uidlevel2","uidlevel3","uidlevel4","ou","ouname","oucode","oulevel","eventdatavalues","eventgeometry", - "evlongitude","evlatitude","ounamehierarchy") select distinct te.uid,p.uid,en.uid,ps.uid,ev.uid,ev.occurreddate,ev.lastupdated, - ev.created,ev.scheduleddate,ev.status,ous.uidlevel1,ous.uidlevel2,ous.uidlevel3,ous.uidlevel4,ous.organisationunituid,ous.name,ous.code,ous.level, - %s, - ev.geometry,case when 'POINT' = GeometryType(ev.geometry) then ST_X(ev.geometry) end,case when 'POINT' = GeometryType(ev.geometry) then ST_Y(ev.geometry) end,concat_ws(' / ',) as ounamehierarchy - from "event" ev inner join "enrollment" en on en.enrollmentid=ev.enrollmentid - and en.deleted = false inner join "trackedentity" te on te.trackedentityid=en.trackedentityid - and te.deleted = false and te.trackedentitytypeid = 0 - and te.lastupdated < '2019-08-01T00:00:00' left join "programstage" ps on ev.programstageid=ps.programstageid - left join "program" p on ps.programid=p.programid - left join analytics_rs_orgunitstructure ous on ev.organisationunitid=ous.organisationunitid - where ev.status in ('COMPLETED','ACTIVE','SCHEDULE') - and (CASE WHEN 'SCHEDULE' = ev.status THEN ev.scheduleddate ELSE ev.occurreddate END) >= 'null' - and (CASE WHEN 'SCHEDULE' = ev.status THEN ev.scheduleddate ELSE ev.occurreddate END) < 'null' - and ev.deleted = false""" + insert into analytics_te_event_tetuid_temp ("trackedentity","program","enrollment","programstage","event","occurreddate","lastupdated","created", + "scheduleddate","status","ou","ouname","oucode","oulevel","eventdatavalues","eventgeometry", + "evlongitude","evlatitude","ounamehierarchy") select distinct te.uid,p.uid,en.uid,ps.uid,ev.uid,ev.occurreddate,ev.lastupdated, + ev.created,ev.scheduleddate,ev.status,ous.organisationunituid,ous.name,ous.code,ous.level, + %s, + ev.geometry,case when 'POINT' = GeometryType(ev.geometry) then ST_X(ev.geometry) end,case when 'POINT' = GeometryType(ev.geometry) then ST_Y(ev.geometry) end,concat_ws(' / ',) as ounamehierarchy + from "event" ev inner join "enrollment" en on en.enrollmentid=ev.enrollmentid + and en.deleted = false inner join "trackedentity" te on te.trackedentityid=en.trackedentityid + and te.deleted = false and te.trackedentitytypeid = 0 + and te.lastupdated < '2019-08-01T00:00:00' left join "programstage" ps on ev.programstageid=ps.programstageid + left join "program" p on ps.programid=p.programid + left join analytics_rs_orgunitstructure ous on ev.organisationunitid=ous.organisationunitid + where ev.status in ('COMPLETED','ACTIVE','SCHEDULE') + and (CASE WHEN 'SCHEDULE' = ev.status THEN ev.scheduleddate ELSE ev.occurreddate END) >= 'null' + and (CASE WHEN 'SCHEDULE' = ev.status THEN ev.scheduleddate ELSE ev.occurreddate END) < 'null' + and ev.deleted = false""" .formatted(subQuery); ArgumentCaptor sqlCaptor = ArgumentCaptor.forClass(String.class); diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java index cbd1947a91e8..20265191bce3 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java @@ -47,13 +47,11 @@ * @author Lars Helge Overland */ class PartitionUtilsTest { - private PeriodType quarterly = new QuarterlyPeriodType(); + private final PeriodType quarterly = new QuarterlyPeriodType(); - private Period q1 = quarterly.createPeriod(new DateTime(2018, 7, 1, 0, 0).toDate()); - - private Period q2 = quarterly.createPeriod(new DateTime(2018, 10, 1, 0, 0).toDate()); - - private Period q3 = quarterly.createPeriod(new DateTime(2019, 1, 1, 0, 0).toDate()); + private final Period q1 = quarterly.createPeriod(new DateTime(2018, 7, 1, 0, 0).toDate()); + private final Period q2 = quarterly.createPeriod(new DateTime(2018, 10, 1, 0, 0).toDate()); + private final Period q3 = quarterly.createPeriod(new DateTime(2019, 1, 1, 0, 0).toDate()); @Test void testGetPartitions() { diff --git a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/util/AnalyticsUtilsTest.java b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/util/AnalyticsUtilsTest.java index dbbb563aa2ac..d2b77d2fecbf 100644 --- a/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/util/AnalyticsUtilsTest.java +++ b/dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/util/AnalyticsUtilsTest.java @@ -739,14 +739,6 @@ void testGetEnumCaseSensitivity() { assertNull(EnumUtils.getEnum(Database.class, "postgresql")); } - @Test - void testGetClosingParentheses() { - assertEquals("", AnalyticsUtils.getClosingParentheses(null)); - assertEquals("", AnalyticsUtils.getClosingParentheses("")); - assertEquals(")", AnalyticsUtils.getClosingParentheses("from(select(select (*))")); - assertEquals("))", AnalyticsUtils.getClosingParentheses("((")); - } - @Test void whenUncategorizedSQLException_withTableNotExisting_thenThrowException() { SQLException sqlException = new SQLException("relation does not exist", "42P01"); diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java index 4a8c35fdb85d..160040e2ab88 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueAuditService.java @@ -30,10 +30,10 @@ import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryCombo; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryOptionComboStore; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.period.Period; @@ -134,21 +134,23 @@ public List getDataValueAudits( } // case if the audit trail started out with DELETE - if (dataValueAudits.get(dataValueAudits.size() - 1).getAuditType() == ChangeLogType.DELETE) { + if (dataValueAudits.get(dataValueAudits.size() - 1).getAuditType() + == AuditOperationType.DELETE) { DataValueAudit valueAudit = createDataValueAudit(dataValue); valueAudit.setValue(dataValueAudits.get(dataValueAudits.size() - 1).getValue()); dataValueAudits.add(valueAudit); } // unless top is CREATE, inject current DV as audit on top - if (!dataValue.isDeleted() && dataValueAudits.get(0).getAuditType() != ChangeLogType.CREATE) { + if (!dataValue.isDeleted() + && dataValueAudits.get(0).getAuditType() != AuditOperationType.CREATE) { DataValueAudit dataValueAudit = createDataValueAudit(dataValue); - dataValueAudit.setAuditType(ChangeLogType.UPDATE); + dataValueAudit.setAuditType(AuditOperationType.UPDATE); dataValueAudit.setCreated(dataValue.getLastUpdated()); dataValueAudits.add(0, dataValueAudit); } - dataValueAudits.get(dataValueAudits.size() - 1).setAuditType(ChangeLogType.CREATE); + dataValueAudits.get(dataValueAudits.size() - 1).setAuditType(AuditOperationType.CREATE); return dataValueAudits; } @@ -156,7 +158,7 @@ public List getDataValueAudits( private static DataValueAudit createDataValueAudit(DataValue dataValue) { DataValueAudit dataValueAudit = new DataValueAudit( - dataValue, dataValue.getValue(), dataValue.getStoredBy(), ChangeLogType.CREATE); + dataValue, dataValue.getValue(), dataValue.getStoredBy(), AuditOperationType.CREATE); dataValueAudit.setCreated(dataValue.getCreated()); return dataValueAudit; diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java index 1c733e2dd0af..eb5138b0b2d5 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/datavalue/DefaultDataValueService.java @@ -38,10 +38,10 @@ import javax.annotation.Nonnull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryCombo; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.IllegalQueryException; import org.hisp.dhis.common.UID; import org.hisp.dhis.dataelement.DataElement; @@ -143,7 +143,10 @@ public boolean addDataValue(DataValue dataValue) { if (config.isEnabled(CHANGELOG_AGGREGATE)) { DataValueAudit dataValueAudit = new DataValueAudit( - dataValue, dataValue.getValue(), dataValue.getStoredBy(), ChangeLogType.CREATE); + dataValue, + dataValue.getValue(), + dataValue.getStoredBy(), + AuditOperationType.CREATE); dataValueAuditService.addDataValueAudit(dataValueAudit); } @@ -168,7 +171,7 @@ public void updateDataValue(DataValue dataValue) { dataValue, dataValue.getAuditValue(), dataValue.getStoredBy(), - ChangeLogType.UPDATE); + AuditOperationType.UPDATE); dataValueAuditService.addDataValueAudit(dataValueAudit); } @@ -196,7 +199,7 @@ public void deleteDataValue(DataValue dataValue) { dataValue, dataValue.getAuditValue(), CurrentUserUtil.getCurrentUsername(), - ChangeLogType.DELETE); + AuditOperationType.DELETE); dataValueAuditService.addDataValueAudit(dataValueAudit); } diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/icon/DefaultIconService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/icon/DefaultIconService.java index 46252c6b9ed3..5226c174b114 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/icon/DefaultIconService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/icon/DefaultIconService.java @@ -40,6 +40,7 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; @@ -114,11 +115,13 @@ public String addDefaultIconImage(@Nonnull String key, @Nonnull DefaultIcon orig try { FileResource fr = FileResource.ofKey(ICON, key, MEDIA_TYPE_SVG); fr.setUid(fileResourceId); + Optional existing = fileResourceService.findByStorageKey(fr.getStorageKey()); + if (existing.isPresent()) fr = existing.get(); fr.setAssigned(true); try (InputStream image = resource.getInputStream()) { fileResourceService.syncSaveFileResource(fr, image); } - return fileResourceId; + return fr.getUid(); } catch (IOException ex) { ignoredAfterFailure.add(origin); throw new ConflictException("Failed to create default icon resource: " + ex.getMessage()); diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/TrackedEntityDataValueChangeLogDeletionHandler.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/EventChangeLogDeletionHandler.java similarity index 88% rename from dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/TrackedEntityDataValueChangeLogDeletionHandler.java rename to dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/EventChangeLogDeletionHandler.java index 11a6b0e7d97e..e7320c4d48e0 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/TrackedEntityDataValueChangeLogDeletionHandler.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/EventChangeLogDeletionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2022, University of Oslo + * Copyright (c) 2004-2024, University of Oslo * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +38,7 @@ */ @Component @RequiredArgsConstructor -public class TrackedEntityDataValueChangeLogDeletionHandler extends JdbcDeletionHandler { +public class EventChangeLogDeletionHandler extends JdbcDeletionHandler { @Override protected void register() { @@ -46,9 +46,6 @@ protected void register() { } private void deleteDataElement(DataElement dataElement) { - delete( - "delete from trackedentitydatavalueaudit where dataelementid = :id", - Map.of("id", dataElement.getId())); delete( "delete from eventchangelog where dataelementid = :id", Map.of("id", dataElement.getId())); } diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DefaultProgramMessageService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DefaultProgramMessageService.java index f521456e605b..4853a23a6624 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DefaultProgramMessageService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DefaultProgramMessageService.java @@ -27,7 +27,7 @@ */ package org.hisp.dhis.program.message; -import static org.hisp.dhis.changelog.ChangeLogType.READ; +import static org.hisp.dhis.audit.AuditOperationType.READ; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUsername; import java.util.ArrayList; diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DeliveryChannelStrategy.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DeliveryChannelStrategy.java index 368a9c2a30fc..2f6fda80b648 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DeliveryChannelStrategy.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/program/message/DeliveryChannelStrategy.java @@ -27,7 +27,7 @@ */ package org.hisp.dhis.program.message; -import static org.hisp.dhis.changelog.ChangeLogType.READ; +import static org.hisp.dhis.audit.AuditOperationType.READ; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUsername; import java.util.Set; diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaCriteriaQueryEngine.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaCriteriaQueryEngine.java index 9f9a02b251c7..8a3176f33286 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaCriteriaQueryEngine.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaCriteriaQueryEngine.java @@ -221,15 +221,13 @@ private InternalHibernateGenericStore getStore private Predicate buildPredicates(CriteriaBuilder builder, Root root, Query query) { Predicate junction = builder.conjunction(); - if (query.isEmpty()) return junction; - query.getAliases().forEach(alias -> root.join(alias).alias(alias)); if (!query.getCriterions().isEmpty()) { junction = getJpaJunction(builder, query.getRootJunctionType()); for (org.hisp.dhis.query.Criterion criterion : query.getCriterions()) { addPredicate(builder, root, junction, criterion); } } - + query.getAliases().forEach(alias -> root.get(alias).alias(alias)); return junction; } @@ -245,6 +243,7 @@ private Predicate getPredicate( if (restriction == null || restriction.getOperator() == null) { return null; } + return restriction.getOperator().getPredicate(builder, root, restriction.getQueryPath()); } @@ -253,7 +252,8 @@ private void addPredicate( Root root, Predicate predicateJunction, org.hisp.dhis.query.Criterion criterion) { - if (criterion instanceof Restriction restriction) { + if (criterion instanceof Restriction) { + Restriction restriction = (Restriction) criterion; Predicate predicate = getPredicate(builder, root, restriction); if (predicate != null) { @@ -281,7 +281,8 @@ private void addJunction( Root root, Predicate junction, org.hisp.dhis.query.Criterion criterion) { - if (criterion instanceof Restriction restriction) { + if (criterion instanceof Restriction) { + Restriction restriction = (Restriction) criterion; Predicate predicate = getPredicate(builder, root, restriction); if (predicate != null) { diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaQueryUtils.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaQueryUtils.java index 58768be647bf..fd63fdf1366a 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaQueryUtils.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/JpaQueryUtils.java @@ -31,6 +31,7 @@ import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Order; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; @@ -51,6 +52,12 @@ public class JpaQueryUtils { public static final String HIBERNATE_CACHEABLE_HINT = "org.hibernate.cacheable"; + public static Function, Order> getOrders(CriteriaBuilder builder, String field) { + Function, Order> order = root -> builder.asc(root.get(field)); + + return order; + } + /** * Generate a String comparison Predicate base on input parameters. * diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/EqualOperator.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/EqualOperator.java index 4a521ca46d42..eca23c6e0e50 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/EqualOperator.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/EqualOperator.java @@ -28,7 +28,6 @@ package org.hisp.dhis.query.operators; import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import java.util.Collection; @@ -87,13 +86,6 @@ public Predicate getPredicate(CriteriaBuilder builder, Root root, QueryPa return builder.equal(builder.size(root.get(queryPath.getPath())), value); } - if (queryPath.haveAlias()) { - for (Join join : root.getJoins()) { - if (join.getAlias().equals(queryPath.getAlias()[0])) { - return builder.equal(join.get(queryPath.getProperty().getFieldName()), args.get(0)); - } - } - } return builder.equal(root.get(queryPath.getPath()), args.get(0)); } diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/InOperator.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/InOperator.java index 2156d37fb07f..3670033e5978 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/InOperator.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/operators/InOperator.java @@ -28,7 +28,6 @@ package org.hisp.dhis.query.operators; import jakarta.persistence.criteria.CriteriaBuilder; -import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import java.util.Collection; @@ -79,13 +78,7 @@ public Predicate getPredicate(CriteriaBuilder builder, Root root, QueryPa queryPath.getProperty().getItemKlass(), getCollectionArgs().get(0))); } - if (queryPath.haveAlias()) { - for (Join join : root.getJoins()) { - if (join.getAlias().equals(queryPath.getAlias()[0])) { - return join.get(queryPath.getProperty().getFieldName()).in(getCollectionArgs().get(0)); - } - } - } + return root.get(queryPath.getPath()).in(getCollectionArgs().get(0)); } diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/planner/DefaultQueryPlanner.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/planner/DefaultQueryPlanner.java index cf5e5757b1d7..1757a0c573b9 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/planner/DefaultQueryPlanner.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/planner/DefaultQueryPlanner.java @@ -217,12 +217,14 @@ private Query getQuery(Query query, boolean persistedOnly) { setQueryPathLocale(restriction); } - if (restriction.getQueryPath().isPersisted() && !isAttributeFilter(query, restriction)) { + if (restriction.getQueryPath().isPersisted() + && !restriction.getQueryPath().haveAlias() + && !Attribute.ObjectType.isValidType(restriction.getQueryPath().getPath())) { + pQuery + .getAliases() + .addAll(Arrays.asList(((Restriction) criterion).getQueryPath().getAlias())); pQuery.getCriterions().add(criterion); iterator.remove(); - if (restriction.getQueryPath().haveAlias()) { - pQuery.getAliases().addAll(Arrays.asList(restriction.getQueryPath().getAlias())); - } } } } @@ -264,15 +266,14 @@ private Junction handleJunction(Query query, Junction queryJunction, boolean per setQueryPathLocale(restriction); } - if (restriction.getQueryPath().isPersisted() && !isAttributeFilter(query, restriction)) { - if (restriction.getQueryPath().haveAlias()) { - criteriaJunction - .getAliases() - .addAll(Arrays.asList(restriction.getQueryPath().getAlias())); - } + if (restriction.getQueryPath().isPersisted() + && !restriction.getQueryPath().haveAlias(1) + && !Attribute.ObjectType.isValidType(restriction.getQueryPath().getPath())) { + criteriaJunction + .getAliases() + .addAll(Arrays.asList(((Restriction) criterion).getQueryPath().getAlias())); criteriaJunction.getCriterions().add(criterion); iterator.remove(); - } else if (persistedOnly) { throw new RuntimeException( "Path " @@ -299,14 +300,4 @@ private boolean isFilterByAttributeId(Property curProperty, String propertyName) private void setQueryPathLocale(Restriction restriction) { restriction.getQueryPath().setLocale(UserSettings.getCurrentSettings().getUserDbLocale()); } - - /** - * Handle attribute filter such as /attributes?fields=id,name&filter=userAttribute:eq:true - * - * @return true if attribute filter - */ - private boolean isAttributeFilter(Query query, Restriction restriction) { - return query.getSchema().getKlass().isAssignableFrom(Attribute.class) - && Attribute.ObjectType.isValidType(restriction.getQueryPath().getPath()); - } } diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/trackedentity/DefaultApiTrackedEntityAuditService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/trackedentity/DefaultApiTrackedEntityAuditService.java index 024c36c96caf..b68ef567ac7b 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/trackedentity/DefaultApiTrackedEntityAuditService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/trackedentity/DefaultApiTrackedEntityAuditService.java @@ -28,7 +28,7 @@ package org.hisp.dhis.trackedentity; import lombok.RequiredArgsConstructor; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -45,13 +45,13 @@ public class DefaultApiTrackedEntityAuditService implements ApiTrackedEntityAudi @Async @Transactional public void addTrackedEntityAudit( - TrackedEntity trackedEntity, String username, ChangeLogType changeLogType) { + TrackedEntity trackedEntity, String username, AuditOperationType auditOperationType) { if (username != null && trackedEntity != null && trackedEntity.getTrackedEntityType() != null && trackedEntity.getTrackedEntityType().isAllowAuditLog()) { TrackedEntityAudit trackedEntityAudit = - new TrackedEntityAudit(trackedEntity.getUid(), username, changeLogType); + new TrackedEntityAudit(trackedEntity.getUid(), username, auditOperationType); apiTrackedEntityAuditStore.addTrackedEntityAudit(trackedEntityAudit); } } diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties b/dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties index 02bace0e18d3..e2b3adaf7d98 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/i18n_global.properties @@ -2128,6 +2128,7 @@ data_integrity.user_roles_no_authorities.name=User roles with no authorities data_integrity.user_roles_with_no_users.name=User roles with no users data_integrity.option_groups_empty.users=Option groups with no options data_integrity.push_analysis_no_recipients.name=Push analyses without recipients +data_integrity.file_resources_no_icon.name=File resources that are missing an icon # -- End Data Integrity Checks--------------------------------------------# diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml index a0358b2e5eeb..b316a01aa4a3 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/datavalue/hibernate/DataValueAudit.hbm.xml @@ -35,7 +35,7 @@ - org.hisp.dhis.changelog.ChangeLogType + org.hisp.dhis.audit.AuditOperationType true 12 diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAudit.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAudit.hbm.xml index 6778f22e8dca..b10aafe0aa14 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAudit.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAudit.hbm.xml @@ -19,7 +19,7 @@ - org.hisp.dhis.changelog.ChangeLogType + org.hisp.dhis.audit.AuditOperationType true 12 diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentityattributevalue/hibernate/TrackedEntityAttributeValueChangeLog.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentityattributevalue/hibernate/TrackedEntityAttributeValueChangeLog.hbm.xml deleted file mode 100644 index 4a25ce8de9bf..000000000000 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentityattributevalue/hibernate/TrackedEntityAttributeValueChangeLog.hbm.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - org.hisp.dhis.changelog.ChangeLogType - true - 12 - - - - - diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentitydatavalue/hibernate/TrackedEntityDataValueChangeLog.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentitydatavalue/hibernate/TrackedEntityDataValueChangeLog.hbm.xml deleted file mode 100644 index 34fbecd51dda..000000000000 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/trackedentitydatavalue/hibernate/TrackedEntityDataValueChangeLog.hbm.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - trackedentitydatavalueaudit_sequence - - - - - - - - - - - - - - - - - - org.hisp.dhis.changelog.ChangeLogType - true - 12 - - - - - diff --git a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java index 5105bda60b0a..ff6497632025 100644 --- a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java +++ b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java @@ -54,10 +54,10 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.BooleanUtils; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.calendar.CalendarService; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.DxfNamespaces; import org.hisp.dhis.common.IdScheme; import org.hisp.dhis.common.IdSchemes; @@ -933,7 +933,7 @@ private void saveDataValueDelete( internalValue, existingValue.getValue(), context.getStoredBy(dataValue), - ChangeLogType.DELETE); + AuditOperationType.DELETE); context.getAuditBatchHandler().addObject(auditValue); } @@ -947,13 +947,13 @@ private void saveDataValueUpdate( ImportContext.DataValueContext valueContext, DataValue internalValue, DataValue existingValue) { - ChangeLogType changeLogType = ChangeLogType.UPDATE; + AuditOperationType auditOperationType = AuditOperationType.UPDATE; if (internalValue.isNullValue() || internalValue.isDeleted() || dataValueIsZeroAndInsignificant(dataValue.getValue(), valueContext.getDataElement())) { internalValue.setDeleted(true); - changeLogType = ChangeLogType.DELETE; + auditOperationType = AuditOperationType.DELETE; importCount.incrementDeleted(); } else { @@ -972,14 +972,14 @@ private void saveDataValueUpdate( internalValue, existingValue.getValue(), context.getStoredBy(dataValue), - changeLogType); + auditOperationType); context.getAuditBatchHandler().addObject(auditValue); } if (valueContext.getDataElement().isFileType()) { FileResource fr = fileResourceService.getFileResource(existingValue.getValue()); - if (changeLogType == ChangeLogType.DELETE) { + if (auditOperationType == AuditOperationType.DELETE) { fileResourceService.deleteFileResource(fr); } else { if (fr != null && !fr.isAssigned()) { diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/DefaultTrackedEntityAuditService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/DefaultTrackedEntityAuditService.java index 2b26663a9de9..ac78c77f92c5 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/DefaultTrackedEntityAuditService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/DefaultTrackedEntityAuditService.java @@ -29,7 +29,7 @@ import java.util.List; import lombok.RequiredArgsConstructor; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.trackedentity.TrackedEntity; import org.hisp.dhis.trackedentity.TrackedEntityAudit; @@ -57,13 +57,13 @@ public class DefaultTrackedEntityAuditService implements TrackedEntityAuditServi @Async @Transactional public void addTrackedEntityAudit( - TrackedEntity trackedEntity, String username, ChangeLogType changeLogType) { + TrackedEntity trackedEntity, String username, AuditOperationType auditOperationType) { if (username != null && trackedEntity != null && trackedEntity.getTrackedEntityType() != null && trackedEntity.getTrackedEntityType().isAllowAuditLog()) { TrackedEntityAudit trackedEntityAudit = - new TrackedEntityAudit(trackedEntity.getUid(), username, changeLogType); + new TrackedEntityAudit(trackedEntity.getUid(), username, auditOperationType); trackedEntityAuditStore.addTrackedEntityAudit(trackedEntityAudit); } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/TrackedEntityAuditService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/TrackedEntityAuditService.java index a789b550fa5d..b8ae73a1983e 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/TrackedEntityAuditService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/audit/TrackedEntityAuditService.java @@ -28,7 +28,7 @@ package org.hisp.dhis.tracker.audit; import java.util.List; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.trackedentity.TrackedEntity; import org.hisp.dhis.trackedentity.TrackedEntityAudit; import org.hisp.dhis.trackedentity.TrackedEntityAuditQueryParams; @@ -41,7 +41,7 @@ public interface TrackedEntityAuditService { String ID = TrackedEntityAuditService.class.getName(); void addTrackedEntityAudit( - TrackedEntity trackedEntity, String username, ChangeLogType changeLogType); + TrackedEntity trackedEntity, String username, AuditOperationType auditOperationType); /** Adds multiple tracked entity audit */ void addTrackedEntityAudit(List trackedEntityAudits); diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/OperationsParamsValidator.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/OperationsParamsValidator.java index 9fc3c83f4a5c..26ef82f9ee46 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/OperationsParamsValidator.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/OperationsParamsValidator.java @@ -27,7 +27,7 @@ */ package org.hisp.dhis.tracker.export; -import static org.hisp.dhis.changelog.ChangeLogType.READ; +import static org.hisp.dhis.audit.AuditOperationType.READ; import static org.hisp.dhis.security.Authorities.F_TRACKED_ENTITY_INSTANCE_SEARCH_IN_ALL_ORGUNITS; import java.util.HashSet; diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/DefaultEventChangeLogService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/DefaultEventChangeLogService.java index e61d98e503e2..3a9d0f77b023 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/DefaultEventChangeLogService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/DefaultEventChangeLogService.java @@ -27,6 +27,10 @@ */ package org.hisp.dhis.tracker.export.event; +import static org.hisp.dhis.changelog.ChangeLogType.CREATE; +import static org.hisp.dhis.changelog.ChangeLogType.DELETE; +import static org.hisp.dhis.changelog.ChangeLogType.UPDATE; + import java.text.SimpleDateFormat; import java.util.Date; import java.util.Objects; @@ -143,11 +147,11 @@ private void logIfChanged( private ChangeLogType getChangeLogType(String oldValue, String newValue) { if (isFieldCreated(oldValue, newValue)) { - return ChangeLogType.CREATE; + return CREATE; } else if (isFieldUpdated(oldValue, newValue)) { - return ChangeLogType.UPDATE; + return UPDATE; } else { - return ChangeLogType.DELETE; + return DELETE; } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/TrackedEntityDataValueChangeLog.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/TrackedEntityDataValueChangeLog.java deleted file mode 100644 index e168a78e79bd..000000000000 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/TrackedEntityDataValueChangeLog.java +++ /dev/null @@ -1,205 +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.tracker.export.event; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; -import java.io.Serializable; -import java.util.Date; -import java.util.Objects; -import org.hisp.dhis.changelog.ChangeLogType; -import org.hisp.dhis.common.DxfNamespaces; -import org.hisp.dhis.dataelement.DataElement; -import org.hisp.dhis.program.Event; - -/** - * @author Morten Olav Hansen - */ -@JacksonXmlRootElement(localName = "trackedEntityDataValueAudit", namespace = DxfNamespaces.DXF_2_0) -public class TrackedEntityDataValueChangeLog implements Serializable { - private long id; - - private DataElement dataElement; - - private Event event; - - private Date created; - - private String value; - - private Boolean providedElsewhere; - - private String modifiedBy; - - private ChangeLogType auditType; - - // ------------------------------------------------------------------------- - // Constructors - // ------------------------------------------------------------------------- - - public TrackedEntityDataValueChangeLog() {} - - public TrackedEntityDataValueChangeLog( - DataElement dataElement, - Event event, - String value, - String modifiedBy, - boolean providedElsewhere, - ChangeLogType auditType) { - this.dataElement = dataElement; - this.event = event; - this.providedElsewhere = providedElsewhere; - this.created = new Date(); - this.value = value; - this.modifiedBy = modifiedBy; - this.auditType = auditType; - } - - @Override - public int hashCode() { - return Objects.hash( - dataElement, event, created, value, providedElsewhere, modifiedBy, auditType); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - final TrackedEntityDataValueChangeLog other = (TrackedEntityDataValueChangeLog) obj; - - return Objects.equals(this.dataElement, other.dataElement) - && Objects.equals(this.event, other.event) - && Objects.equals(this.created, other.created) - && Objects.equals(this.value, other.value) - && Objects.equals(this.providedElsewhere, other.providedElsewhere) - && Objects.equals(this.modifiedBy, other.modifiedBy) - && Objects.equals(this.auditType, other.auditType); - } - - @Override - public String toString() { - return "[dataElement: '" - + dataElement.getUid() - + "', " - + "event: '" - + event.getUid() - + "', " - + "value: '" - + value - + "']"; - } - - // ------------------------------------------------------------------------- - // Getters and setters - // ------------------------------------------------------------------------- - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public Event getEvent() { - return event; - } - - public void setEvent(Event event) { - this.event = event; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public DataElement getDataElement() { - return dataElement; - } - - public void setDataElement(DataElement dataElement) { - this.dataElement = dataElement; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public boolean getProvidedElsewhere() { - return providedElsewhere; - } - - public void setProvidedElsewhere(boolean providedElsewhere) { - this.providedElsewhere = providedElsewhere; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public String getModifiedBy() { - return modifiedBy; - } - - public void setModifiedBy(String modifiedBy) { - this.modifiedBy = modifiedBy; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public ChangeLogType getAuditType() { - return auditType; - } - - public void setAuditType(ChangeLogType auditType) { - this.auditType = auditType; - } -} diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/TrackedEntityDataValueChangeLogQueryParams.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/TrackedEntityDataValueChangeLogQueryParams.java deleted file mode 100644 index db22ad67027e..000000000000 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/TrackedEntityDataValueChangeLogQueryParams.java +++ /dev/null @@ -1,74 +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.tracker.export.event; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import lombok.Data; -import lombok.experimental.Accessors; -import org.hisp.dhis.changelog.ChangeLogType; -import org.hisp.dhis.common.OrganisationUnitSelectionMode; -import org.hisp.dhis.common.Pager; -import org.hisp.dhis.dataelement.DataElement; -import org.hisp.dhis.organisationunit.OrganisationUnit; -import org.hisp.dhis.program.Event; -import org.hisp.dhis.program.ProgramStage; - -/** - * @author Lars Helge Overland - */ -@Data -@Accessors(chain = true) -public class TrackedEntityDataValueChangeLogQueryParams { - private List dataElements = new ArrayList<>(); - - private List orgUnits = new ArrayList<>(); - - private List events = new ArrayList<>(); - - private List programStages = new ArrayList<>(); - - private Date startDate; - - private Date endDate; - - private OrganisationUnitSelectionMode ouMode; - - private List auditTypes = new ArrayList<>(); - - private Pager pager; - - public boolean hasOuMode() { - return ouMode != null; - } - - public boolean hasPaging() { - return pager != null; - } -} diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java index a17f1e891b33..7932f4a7510e 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/DefaultTrackedEntityService.java @@ -27,7 +27,8 @@ */ package org.hisp.dhis.tracker.export.trackedentity; -import static org.hisp.dhis.changelog.ChangeLogType.READ; +import static org.hisp.dhis.audit.AuditOperationType.READ; +import static org.hisp.dhis.audit.AuditOperationType.SEARCH; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUserDetails; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUsername; @@ -41,7 +42,6 @@ import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import lombok.RequiredArgsConstructor; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.BaseIdentifiableObject; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.UID; @@ -397,7 +397,10 @@ private Set getEnrollments( e -> { Set filteredEvents = e.getEvents().stream() - .filter(event -> includeDeleted || !event.isDeleted()) + .filter( + event -> + (includeDeleted || !event.isDeleted()) + && trackerAccessManager.canRead(user, event, false).isEmpty()) .collect(Collectors.toSet()); e.setEvents(filteredEvents); return e; @@ -651,7 +654,7 @@ private void addSearchAudit(List trackedEntities) { .map( te -> new TrackedEntityAudit( - te.getUid(), CurrentUserUtil.getCurrentUsername(), ChangeLogType.SEARCH)) + te.getUid(), CurrentUserUtil.getCurrentUsername(), SEARCH)) .toList(); if (!auditable.isEmpty()) { diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityAttributeValueChangeLog.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityAttributeValueChangeLog.java deleted file mode 100644 index ac07c8574644..000000000000 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityAttributeValueChangeLog.java +++ /dev/null @@ -1,207 +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.tracker.export.trackedentity; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; -import java.io.Serializable; -import java.util.Date; -import java.util.Objects; -import org.hisp.dhis.changelog.ChangeLogType; -import org.hisp.dhis.common.DxfNamespaces; -import org.hisp.dhis.trackedentity.TrackedEntity; -import org.hisp.dhis.trackedentity.TrackedEntityAttribute; -import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue; - -/** - * @author Morten Olav Hansen - */ -@JacksonXmlRootElement( - localName = "trackedEntityAttributeValueAudit", - namespace = DxfNamespaces.DXF_2_0) -public class TrackedEntityAttributeValueChangeLog implements Serializable { - private long id; - - private TrackedEntityAttribute attribute; - - private TrackedEntity trackedEntity; - - private Date created; - - private String plainValue; - - private String encryptedValue; - - private String modifiedBy; - - private ChangeLogType auditType; - - /** - * This value is only used to store values from setValue when we don't know if attribute is set or - * not. - */ - private String value; - - public TrackedEntityAttributeValueChangeLog() {} - - public TrackedEntityAttributeValueChangeLog( - TrackedEntityAttributeValue trackedEntityAttributeValue, - String value, - String modifiedBy, - ChangeLogType auditType) { - this.attribute = trackedEntityAttributeValue.getAttribute(); - this.trackedEntity = trackedEntityAttributeValue.getTrackedEntity(); - - this.created = new Date(); - this.value = value; - this.modifiedBy = modifiedBy; - this.auditType = auditType; - } - - @Override - public int hashCode() { - return Objects.hash(attribute, trackedEntity, created, getValue(), modifiedBy, auditType); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - final TrackedEntityAttributeValueChangeLog other = (TrackedEntityAttributeValueChangeLog) obj; - - return Objects.equals(this.attribute, other.attribute) - && Objects.equals(this.trackedEntity, other.trackedEntity) - && Objects.equals(this.created, other.created) - && Objects.equals(this.getValue(), other.getValue()) - && Objects.equals(this.modifiedBy, other.modifiedBy) - && Objects.equals(this.auditType, other.auditType); - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getPlainValue() { - return (Boolean.FALSE.equals(getAttribute().getConfidential()) && this.value != null - ? this.value - : this.plainValue); - } - - public void setPlainValue(String plainValue) { - this.plainValue = plainValue; - } - - public String getEncryptedValue() { - return (Boolean.TRUE.equals(getAttribute().getConfidential()) && this.value != null - ? this.value - : this.encryptedValue); - } - - public void setEncryptedValue(String encryptedValue) { - this.encryptedValue = encryptedValue; - } - - @JsonProperty("trackedEntityAttribute") - @JacksonXmlProperty(localName = "trackedEntityAttribute", namespace = DxfNamespaces.DXF_2_0) - public TrackedEntityAttribute getAttribute() { - return attribute; - } - - public void setAttribute(TrackedEntityAttribute attribute) { - this.attribute = attribute; - } - - @JsonProperty("trackedEntityInstance") - @JacksonXmlProperty(localName = "trackedEntityInstance", namespace = DxfNamespaces.DXF_2_0) - public TrackedEntity getTrackedEntity() { - return trackedEntity; - } - - public void setTrackedEntity(TrackedEntity trackedEntity) { - this.trackedEntity = trackedEntity; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public String getValue() { - return (Boolean.TRUE.equals(getAttribute().getConfidential()) - ? this.getEncryptedValue() - : this.getPlainValue()); - } - - /** - * Property which temporarily stores the attribute value. The {@link #getEncryptedValue} and - * {@link #getPlainValue} methods handle the value when requested. - * - * @param value the value to be stored. - */ - public void setValue(String value) { - this.value = value; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public String getModifiedBy() { - return modifiedBy; - } - - public void setModifiedBy(String modifiedBy) { - this.modifiedBy = modifiedBy; - } - - @JsonProperty - @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) - public ChangeLogType getAuditType() { - return auditType; - } - - public void setAuditType(ChangeLogType auditType) { - this.auditType = auditType; - } -} diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/AbstractTrackerPersister.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/AbstractTrackerPersister.java index 7c74fb2ed93b..22862bf9d037 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/AbstractTrackerPersister.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/AbstractTrackerPersister.java @@ -28,6 +28,9 @@ package org.hisp.dhis.tracker.imports.bundle.persister; import static com.google.common.base.Preconditions.checkNotNull; +import static org.hisp.dhis.changelog.ChangeLogType.CREATE; +import static org.hisp.dhis.changelog.ChangeLogType.DELETE; +import static org.hisp.dhis.changelog.ChangeLogType.UPDATE; import jakarta.persistence.EntityManager; import java.util.ArrayList; @@ -53,7 +56,6 @@ import org.hisp.dhis.trackedentityattributevalue.TrackedEntityAttributeValue; import org.hisp.dhis.tracker.TrackerIdSchemeParams; import org.hisp.dhis.tracker.TrackerType; -import org.hisp.dhis.tracker.export.trackedentity.TrackedEntityAttributeValueChangeLog; import org.hisp.dhis.tracker.export.trackedentity.TrackedEntityChangeLogService; import org.hisp.dhis.tracker.imports.AtomicMode; import org.hisp.dhis.tracker.imports.FlushMode; @@ -409,7 +411,7 @@ private void delete( trackedEntityAttributeValue.getPlainValue(), null, trackedEntity, - ChangeLogType.DELETE); + DELETE); } private void saveOrUpdate( @@ -433,12 +435,12 @@ private void saveOrUpdate( // In case it's a newly created attribute we'll add it back to TE, // so it can end up in preheat trackedEntity.getTrackedEntityAttributeValues().add(trackedEntityAttributeValue); - changeLogType = ChangeLogType.CREATE; + changeLogType = CREATE; } else { entityManager.merge(trackedEntityAttributeValue); if (isUpdated) { - changeLogType = ChangeLogType.UPDATE; + changeLogType = UPDATE; } } @@ -486,11 +488,6 @@ private void addTrackedEntityChangeLog( boolean allowAuditLog = trackedEntity.getTrackedEntityType().isAllowAuditLog(); if (allowAuditLog && changeLogType != null) { - TrackedEntityAttributeValueChangeLog valueAudit = - new TrackedEntityAttributeValueChangeLog( - attributeValue, attributeValue.getPlainValue(), userName, changeLogType); - valueAudit.setTrackedEntity(trackedEntity); - trackedEntityChangeLogService.addTrackedEntityChangeLog( trackedEntity, attributeValue.getAttribute(), diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/DefaultTrackerObjectsDeletionService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/DefaultTrackerObjectsDeletionService.java index f93c8fcf41ba..4132fc0fbe86 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/DefaultTrackerObjectsDeletionService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/bundle/persister/DefaultTrackerObjectsDeletionService.java @@ -27,7 +27,7 @@ */ package org.hisp.dhis.tracker.imports.bundle.persister; -import static org.hisp.dhis.changelog.ChangeLogType.READ; +import static org.hisp.dhis.audit.AuditOperationType.READ; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUserDetails; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUsername; diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/trackedentityattributevalue/DefaultTrackedEntityAttributeValueService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/trackedentityattributevalue/DefaultTrackedEntityAttributeValueService.java index 3ce4fd0d872d..3738462d28d5 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/trackedentityattributevalue/DefaultTrackedEntityAttributeValueService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/trackedentityattributevalue/DefaultTrackedEntityAttributeValueService.java @@ -27,6 +27,7 @@ */ package org.hisp.dhis.tracker.trackedentityattributevalue; +import static org.hisp.dhis.changelog.ChangeLogType.DELETE; import static org.hisp.dhis.external.conf.ConfigurationKey.CHANGELOG_TRACKER; import static org.hisp.dhis.system.util.ValidationUtils.valueIsValid; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUsername; @@ -35,7 +36,6 @@ import java.util.Map; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.IllegalQueryException; import org.hisp.dhis.external.conf.DhisConfigurationProvider; import org.hisp.dhis.fileresource.FileResource; @@ -71,7 +71,7 @@ public void deleteTrackedEntityAttributeValue(TrackedEntityAttributeValue attrib attributeValue.getAttribute(), attributeValue.getPlainValue(), null, - ChangeLogType.DELETE, + DELETE, getCurrentUsername()); } diff --git a/dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java b/dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java index 15d0c5154408..e0923fb6f83a 100644 --- a/dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java +++ b/dhis-2/dhis-support/dhis-support-external/src/main/java/org/hisp/dhis/external/conf/ConfigurationKey.java @@ -136,12 +136,6 @@ public enum ConfigurationKey { /** Sets 'hibernate.cache.use_query_cache'. (default: true) */ USE_QUERY_CACHE("hibernate.cache.use_query_cache", "true", false), - /** - * Show SQL statements generated by hibernate in the log. Can be 'true', 'false'. (default: false) - * This will also enable hibernate.format_sql and hibernate.highlight_sql - */ - HIBERNATE_SHOW_SQL("hibernate.show_sql", "false", false), - /** * Sets 'hibernate.hbm2ddl.auto' (default: validate). This can be overridden by the same property * loaded by any class implementing {@link DhisConfigurationProvider} like {@link diff --git a/dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/config/HibernateConfig.java b/dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/config/HibernateConfig.java index c905728d2090..68a36b8bd772 100644 --- a/dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/config/HibernateConfig.java +++ b/dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/config/HibernateConfig.java @@ -183,14 +183,6 @@ private Properties getAdditionalProperties(DhisConfigurationProvider dhisConfig) properties.put(AvailableSettings.HBM2DDL_AUTO, getHibernateSchemaAction(dhisConfig)); - properties.put( - AvailableSettings.SHOW_SQL, dhisConfig.getProperty(ConfigurationKey.HIBERNATE_SHOW_SQL)); - properties.put( - AvailableSettings.FORMAT_SQL, dhisConfig.getProperty(ConfigurationKey.HIBERNATE_SHOW_SQL)); - properties.put( - AvailableSettings.HIGHLIGHT_SQL, - dhisConfig.getProperty(ConfigurationKey.HIBERNATE_SHOW_SQL)); - // TODO: this is anti-pattern and should be turn off properties.put("hibernate.allow_update_outside_transaction", "true"); diff --git a/dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandler.java b/dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandler.java index d9a7e120566a..3538b406168c 100644 --- a/dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandler.java +++ b/dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandler.java @@ -32,7 +32,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.datavalue.DataValueAudit; import org.hisp.quick.JdbcConfiguration; import org.hisp.quick.batchhandler.AbstractBatchHandler; @@ -123,7 +123,7 @@ public DataValueAudit mapRow(ResultSet resultSet) throws SQLException { dva.setValue(resultSet.getString("value")); dva.setModifiedBy(resultSet.getString("modifiedby")); dva.setCreated(resultSet.getDate("created")); - dva.setAuditType(ChangeLogType.valueOf(resultSet.getString("audittype"))); + dva.setAuditType(AuditOperationType.valueOf(resultSet.getString("audittype"))); return dva; } diff --git a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/ClickHouseSqlBuilder.java b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/ClickHouseSqlBuilder.java index f763eace89e7..6381be607075 100644 --- a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/ClickHouseSqlBuilder.java +++ b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/ClickHouseSqlBuilder.java @@ -164,6 +164,11 @@ public boolean supportsVacuum() { return false; } + @Override + public boolean supportsCorrelatedSubquery() { + return false; + } + @Override public boolean requiresIndexesForAnalytics() { return false; diff --git a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/DorisSqlBuilder.java b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/DorisSqlBuilder.java index e4414841175f..48bfe6bc31b8 100644 --- a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/DorisSqlBuilder.java +++ b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/DorisSqlBuilder.java @@ -166,6 +166,11 @@ public boolean supportsVacuum() { return false; } + @Override + public boolean supportsCorrelatedSubquery() { + return true; + } + @Override public boolean requiresIndexesForAnalytics() { return false; diff --git a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/PostgreSqlBuilder.java b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/PostgreSqlBuilder.java index f28259ce271b..92a14270f8cc 100644 --- a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/PostgreSqlBuilder.java +++ b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/PostgreSqlBuilder.java @@ -185,6 +185,11 @@ public boolean supportsVacuum() { return true; } + @Override + public boolean supportsCorrelatedSubquery() { + return true; + } + @Override public boolean requiresIndexesForAnalytics() { return true; diff --git a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/SqlBuilder.java b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/SqlBuilder.java index 78bbd2d866a4..07016f4c6e8d 100644 --- a/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/SqlBuilder.java +++ b/dhis-2/dhis-support/dhis-support-sql/src/main/java/org/hisp/dhis/db/sql/SqlBuilder.java @@ -174,6 +174,11 @@ public interface SqlBuilder { */ boolean supportsVacuum(); + /** + * @return true if the DBMS supports corrected subqueries. + */ + boolean supportsCorrelatedSubquery(); + /** * @return true if the DBMS requires indexes for analytics tables for performance. */ diff --git a/dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java b/dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java index d7266b8c5368..7ca237a44a47 100644 --- a/dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java +++ b/dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/grid/ListGrid.java @@ -503,11 +503,9 @@ public Grid addColumn(List columnValues) { if (grid.size() != columnValues.size()) { throw new IllegalStateException( - "Number of column values (" - + columnValues.size() - + ") is not equal to number of rows (" - + grid.size() - + ")"); + String.format( + "Number of column values (%d) is not equal to number of rows (%d)", + columnValues.size(), grid.size())); } for (int i = 0; i < grid.size(); i++) { @@ -526,11 +524,9 @@ public Grid addColumn(int columnIndex, List columnValues) { if (grid.size() != columnValues.size()) { throw new IllegalStateException( - "Number of column values (" - + columnValues.size() - + ") is not equal to number of rows (" - + grid.size() - + ")"); + String.format( + "Number of column values (%d) is not equal to number of rows (%d)", + columnValues.size(), grid.size())); } for (int i = 0; i < grid.size(); i++) { @@ -657,7 +653,7 @@ public Grid limitGrid(int limit) { public Grid limitGrid(int startPos, int endPos) { if (startPos < 0 || endPos < startPos || endPos > getHeight()) { throw new IllegalStateException( - "Illegal start / end pos: " + startPos + ", " + endPos + ", " + getHeight()); + "Illegal start or end pos: " + startPos + ", " + endPos + ", " + getHeight()); } grid = grid.subList(startPos, endPos); @@ -813,8 +809,9 @@ public Grid substituteMetaData(Map metaDataMap) { header.setName(String.valueOf(headerMetaName)); } + // Column cells + if (header.isMeta()) { - // Column cells substituteMetaData(colIndex, colIndex, metaDataMap); } @@ -1101,7 +1098,8 @@ public void repositionColumns(List columnIndexes) { row.addAll(orderedValues); } - // reposition columns in the row context structure + // Reposition columns in the row context structure + Map> orderedRowContext = new HashMap<>(); for (Map.Entry> rowContextEntry : rowContext.entrySet()) { @@ -1113,7 +1111,8 @@ public void repositionColumns(List columnIndexes) { .forEach( key -> { if (numberRegex.matcher(key).matches()) { - // reindexing of columns + // Reindexing of columns + orderedRowContextItems.put( columnIndexes.get(Integer.parseInt(key)).toString(), ctxItem.get(key)); } @@ -1151,12 +1150,9 @@ private void verifyGridState() { for (List row : grid) { if (rowLength != null && rowLength != row.size()) { throw new IllegalStateException( - "Grid rows do not have the same number of cells, previous: " - + rowLength - + ", this: " - + row.size() - + ", at row: " - + rowPos); + String.format( + "Grid rows do not have the same number of cells, previous: %d, this: %d, at row: %d", + rowLength, row.size(), rowPos)); } rowPos++; @@ -1177,7 +1173,7 @@ private void updateColumnIndexMap() { } // ------------------------------------------------------------------------- - // toString + // ToString // ------------------------------------------------------------------------- @Override diff --git a/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/merge/CategoryOptionMergeTest.java b/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/merge/CategoryOptionMergeTest.java index db7ad8e0972b..ef31d1cdb97a 100644 --- a/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/merge/CategoryOptionMergeTest.java +++ b/dhis-2/dhis-test-e2e/src/test/java/org/hisp/dhis/merge/CategoryOptionMergeTest.java @@ -45,6 +45,7 @@ import org.hisp.dhis.test.e2e.dto.ApiResponse; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -84,6 +85,7 @@ public void setup() { } @Test + @Disabled("Started failing in GitHub (Not Jenkins) for no obvious reason") @DisplayName( "Valid CategoryOption merge completes successfully with all source CategoryOption refs replaced with target CategoryOption") void validDataElementMergeTest() { @@ -155,6 +157,7 @@ private void setupMetadata() { } @Test + @Disabled("Started failing in GitHub (Not Jenkins) for no obvious reason") @DisplayName("CategoryOption merge fails when user has not got the required authority") void testDataElementMergeNoRequiredAuth() { userActions.addUserFull("basic", "User", "basicUser", "Test1234!", "NO_AUTH"); diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java index 0b926565888b..b3ecc9bae3a2 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/datavalue/DataValueAuditServiceTest.java @@ -31,9 +31,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementService; import org.hisp.dhis.organisationunit.OrganisationUnit; @@ -141,10 +141,10 @@ void setUp() { void testAddGetDataValueAuditFromDataValue() { DataValueAudit dataValueAuditA = new DataValueAudit( - dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), ChangeLogType.UPDATE); + dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), AuditOperationType.UPDATE); DataValueAudit dataValueAuditB = new DataValueAudit( - dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), ChangeLogType.UPDATE); + dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), AuditOperationType.UPDATE); dataValueAuditService.addDataValueAudit(dataValueAuditA); dataValueAuditService.addDataValueAudit(dataValueAuditB); @@ -156,10 +156,10 @@ void testAddGetDataValueAuditFromDataValue() { void testAddGetDataValueAuditSingleRecord() { DataValueAudit dataValueAuditA = new DataValueAudit( - dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), ChangeLogType.UPDATE); + dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), AuditOperationType.UPDATE); DataValueAudit dataValueAuditB = new DataValueAudit( - dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), ChangeLogType.UPDATE); + dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), AuditOperationType.UPDATE); dataValueAuditService.addDataValueAudit(dataValueAuditA); dataValueAuditService.addDataValueAudit(dataValueAuditB); @@ -179,16 +179,16 @@ void testAddGetDataValueAuditSingleRecord() { void testGetDataValueAudit() { DataValueAudit dvaA = new DataValueAudit( - dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), ChangeLogType.UPDATE); + dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), AuditOperationType.UPDATE); DataValueAudit dvaB = new DataValueAudit( - dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), ChangeLogType.UPDATE); + dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), AuditOperationType.UPDATE); DataValueAudit dvaC = new DataValueAudit( - dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), ChangeLogType.CREATE); + dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), AuditOperationType.CREATE); DataValueAudit dvaD = new DataValueAudit( - dataValueD, dataValueD.getValue(), dataValueD.getStoredBy(), ChangeLogType.DELETE); + dataValueD, dataValueD.getValue(), dataValueD.getStoredBy(), AuditOperationType.DELETE); dataValueAuditService.addDataValueAudit(dvaA); dataValueAuditService.addDataValueAudit(dvaB); dataValueAuditService.addDataValueAudit(dvaC); @@ -200,7 +200,7 @@ void testGetDataValueAudit() { .setPeriods(List.of(periodA)) .setOrgUnits(List.of(orgUnitA)) .setCategoryOptionCombo(optionCombo) - .setAuditTypes(List.of(ChangeLogType.UPDATE)); + .setAuditTypes(List.of(AuditOperationType.UPDATE)); assertContainsOnly(List.of(dvaA), dataValueAuditService.getDataValueAudits(params)); @@ -210,17 +210,17 @@ void testGetDataValueAudit() { .setPeriods(List.of(periodA, periodB)) .setOrgUnits(List.of(orgUnitA, orgUnitB)) .setCategoryOptionCombo(optionCombo) - .setAuditTypes(List.of(ChangeLogType.UPDATE)); + .setAuditTypes(List.of(AuditOperationType.UPDATE)); assertContainsOnly(List.of(dvaA, dvaB), dataValueAuditService.getDataValueAudits(params)); - params = new DataValueAuditQueryParams().setAuditTypes(List.of(ChangeLogType.CREATE)); + params = new DataValueAuditQueryParams().setAuditTypes(List.of(AuditOperationType.CREATE)); assertContainsOnly(List.of(dvaC), dataValueAuditService.getDataValueAudits(params)); params = new DataValueAuditQueryParams() - .setAuditTypes(List.of(ChangeLogType.CREATE, ChangeLogType.DELETE)); + .setAuditTypes(List.of(AuditOperationType.CREATE, AuditOperationType.DELETE)); assertContainsOnly(List.of(dvaC, dvaD), dataValueAuditService.getDataValueAudits(params)); } @@ -229,16 +229,16 @@ void testGetDataValueAudit() { void testGetDataValueAuditNoResult() { DataValueAudit dvaA = new DataValueAudit( - dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), ChangeLogType.UPDATE); + dataValueA, dataValueA.getValue(), dataValueA.getStoredBy(), AuditOperationType.UPDATE); DataValueAudit dvaB = new DataValueAudit( - dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), ChangeLogType.UPDATE); + dataValueB, dataValueB.getValue(), dataValueB.getStoredBy(), AuditOperationType.UPDATE); DataValueAudit dvaC = new DataValueAudit( - dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), ChangeLogType.CREATE); + dataValueC, dataValueC.getValue(), dataValueC.getStoredBy(), AuditOperationType.CREATE); DataValueAudit dvaD = new DataValueAudit( - dataValueD, dataValueD.getValue(), dataValueD.getStoredBy(), ChangeLogType.DELETE); + dataValueD, dataValueD.getValue(), dataValueD.getStoredBy(), AuditOperationType.DELETE); dataValueAuditService.addDataValueAudit(dvaA); dataValueAuditService.addDataValueAudit(dvaB); dataValueAuditService.addDataValueAudit(dvaC); @@ -250,7 +250,7 @@ void testGetDataValueAuditNoResult() { .setPeriods(List.of(periodD)) .setOrgUnits(List.of(orgUnitA)) .setCategoryOptionCombo(optionCombo) - .setAuditTypes(List.of(ChangeLogType.UPDATE)); + .setAuditTypes(List.of(AuditOperationType.UPDATE)); assertEquals(0, dataValueAuditService.getDataValueAudits(params).size()); } @@ -263,7 +263,7 @@ void testGetDataValueAuditWithFakeCreate() { .setPeriods(List.of(periodD)) .setOrgUnits(List.of(orgUnitA)) .setCategoryOptionCombo(optionCombo) - .setAuditTypes(List.of(ChangeLogType.UPDATE)); + .setAuditTypes(List.of(AuditOperationType.UPDATE)); assertEquals(0, dataValueAuditService.getDataValueAudits(params).size()); @@ -272,7 +272,7 @@ void testGetDataValueAuditWithFakeCreate() { dataElementA, periodA, orgUnitA, optionCombo, optionCombo); assertEquals(1, audits.size()); - assertEquals(ChangeLogType.CREATE, audits.get(0).getAuditType()); + assertEquals(AuditOperationType.CREATE, audits.get(0).getAuditType()); } @Test @@ -285,43 +285,43 @@ void testGetDataValueAuditWithFakeCreate2() { dataElementA, periodA, orgUnitA, optionCombo, optionCombo); assertEquals(2, audits.size()); - assertEquals(ChangeLogType.UPDATE, audits.get(0).getAuditType()); - assertEquals(ChangeLogType.CREATE, audits.get(1).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(0).getAuditType()); + assertEquals(AuditOperationType.CREATE, audits.get(1).getAuditType()); } @Test void testGetDataValueAuditWithFakeCreateDeleteAndCreate() { dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValueA, "10", dataValueA.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValueA, "10", dataValueA.getStoredBy(), AuditOperationType.UPDATE)); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValueA, "20", dataValueA.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValueA, "20", dataValueA.getStoredBy(), AuditOperationType.UPDATE)); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValueA, "30", dataValueA.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValueA, "30", dataValueA.getStoredBy(), AuditOperationType.UPDATE)); List audits = dataValueAuditService.getDataValueAudits( dataElementA, periodA, orgUnitA, optionCombo, optionCombo); assertEquals(4, audits.size()); - assertEquals(ChangeLogType.CREATE, audits.get(3).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(2).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(1).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(0).getAuditType()); + assertEquals(AuditOperationType.CREATE, audits.get(3).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(2).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(1).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(0).getAuditType()); } @Test @Disabled void testGetDataValueAuditWithFakeCreateDelete2() { dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValueA, "10", dataValueA.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValueA, "10", dataValueA.getStoredBy(), AuditOperationType.UPDATE)); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValueA, "20", dataValueA.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValueA, "20", dataValueA.getStoredBy(), AuditOperationType.UPDATE)); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValueA, "30", dataValueA.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValueA, "30", dataValueA.getStoredBy(), AuditOperationType.UPDATE)); dataValueService.deleteDataValue(dataValueA); @@ -330,10 +330,10 @@ void testGetDataValueAuditWithFakeCreateDelete2() { dataElementA, periodA, orgUnitA, optionCombo, optionCombo); assertEquals(4, audits.size()); - assertEquals(ChangeLogType.CREATE, audits.get(3).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(2).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(1).getAuditType()); - assertEquals(ChangeLogType.DELETE, audits.get(0).getAuditType()); + assertEquals(AuditOperationType.CREATE, audits.get(3).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(2).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(1).getAuditType()); + assertEquals(AuditOperationType.DELETE, audits.get(0).getAuditType()); } @Test @@ -347,13 +347,13 @@ void testGetDataValueAuditWithFakeCreateDeleteAndUndelete() { dataValueService.addDataValue(dataValue); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValue, "10", dataValue.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValue, "10", dataValue.getStoredBy(), AuditOperationType.UPDATE)); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValue, "20", dataValue.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValue, "20", dataValue.getStoredBy(), AuditOperationType.UPDATE)); dataValueAuditService.addDataValueAudit( - new DataValueAudit(dataValue, "30", dataValue.getStoredBy(), ChangeLogType.UPDATE)); + new DataValueAudit(dataValue, "30", dataValue.getStoredBy(), AuditOperationType.UPDATE)); dataValueService.deleteDataValue(dataValue); @@ -370,11 +370,11 @@ void testGetDataValueAuditWithFakeCreateDeleteAndUndelete() { dataElement, periodA, orgUnitA, optionCombo, optionCombo); assertEquals(6, audits.size()); - assertEquals(ChangeLogType.UPDATE, audits.get(0).getAuditType()); - assertEquals(ChangeLogType.CREATE, audits.get(1).getAuditType()); - assertEquals(ChangeLogType.DELETE, audits.get(2).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(3).getAuditType()); - assertEquals(ChangeLogType.UPDATE, audits.get(4).getAuditType()); - assertEquals(ChangeLogType.CREATE, audits.get(5).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(0).getAuditType()); + assertEquals(AuditOperationType.CREATE, audits.get(1).getAuditType()); + assertEquals(AuditOperationType.DELETE, audits.get(2).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(3).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(4).getAuditType()); + assertEquals(AuditOperationType.CREATE, audits.get(5).getAuditType()); } } diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceIntegrationTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceIntegrationTest.java index 076676ed5c59..4986a10eeda2 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceIntegrationTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceIntegrationTest.java @@ -54,12 +54,12 @@ import org.awaitility.Awaitility; import org.hisp.dhis.attribute.Attribute; import org.hisp.dhis.attribute.AttributeService; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.Category; import org.hisp.dhis.category.CategoryCombo; import org.hisp.dhis.category.CategoryOption; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.IdScheme; import org.hisp.dhis.common.IdSchemes; import org.hisp.dhis.common.IdentifiableObjectManager; @@ -1314,7 +1314,7 @@ void testImportDataValuesUpdatedAudit() { () -> String.format( "expected change to dataValue %s to be audited once", dv)); - assertEquals(ChangeLogType.UPDATE, audits.get(0).getAuditType()); + assertEquals(AuditOperationType.UPDATE, audits.get(0).getAuditType()); }) .collect(Collectors.toList())); } diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandlerTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandlerTest.java index bf9b88daf765..6982b81665b2 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandlerTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/jdbc/batchhandler/DataValueAuditBatchHandlerTest.java @@ -32,9 +32,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.List; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementService; import org.hisp.dhis.datavalue.DataValue; @@ -128,10 +128,10 @@ void setUp() { dataElementA, periodA, unitB, categoryOptionComboA, categoryOptionComboA, "10"); dataValueService.addDataValue(dataValueA); dataValueService.addDataValue(dataValueB); - auditA = new DataValueAudit(dataValueA, "11", storedBy, ChangeLogType.UPDATE); - auditB = new DataValueAudit(dataValueA, "12", storedBy, ChangeLogType.UPDATE); - auditC = new DataValueAudit(dataValueB, "21", storedBy, ChangeLogType.UPDATE); - auditD = new DataValueAudit(dataValueB, "22", storedBy, ChangeLogType.UPDATE); + auditA = new DataValueAudit(dataValueA, "11", storedBy, AuditOperationType.UPDATE); + auditB = new DataValueAudit(dataValueA, "12", storedBy, AuditOperationType.UPDATE); + auditC = new DataValueAudit(dataValueB, "21", storedBy, AuditOperationType.UPDATE); + auditD = new DataValueAudit(dataValueB, "22", storedBy, AuditOperationType.UPDATE); } @Test diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/maintenance/MaintenanceServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/maintenance/MaintenanceServiceTest.java index 34f4fc2c6326..c9d7ad93069d 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/maintenance/MaintenanceServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/maintenance/MaintenanceServiceTest.java @@ -27,6 +27,7 @@ */ package org.hisp.dhis.maintenance; +import static org.hisp.dhis.changelog.ChangeLogType.UPDATE; import static org.hisp.dhis.common.OrganisationUnitSelectionMode.ALL; import static org.hisp.dhis.user.CurrentUserUtil.getCurrentUsername; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -48,7 +49,6 @@ import org.hisp.dhis.audit.AuditType; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.CodeGenerator; import org.hisp.dhis.common.DeliveryChannel; import org.hisp.dhis.common.IdentifiableObjectManager; @@ -338,7 +338,7 @@ void testDeleteSoftDeletedEnrollmentLinkedToAnEventDataValueChangeLog() eventA.setOrganisationUnit(organisationUnit); manager.save(eventA); eventChangeLogService.addEventChangeLog( - eventA, dataElement, "", "value", ChangeLogType.UPDATE, getCurrentUsername()); + eventA, dataElement, "", "value", UPDATE, getCurrentUsername()); manager.save(enrollment); assertNotNull(manager.get(Enrollment.class, enrollment.getUid())); manager.delete(enrollment); diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/merge/dataelement/DataElementMergeServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/merge/dataelement/DataElementMergeServiceTest.java index 40e62aeb3201..6404405df508 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/merge/dataelement/DataElementMergeServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/merge/dataelement/DataElementMergeServiceTest.java @@ -40,6 +40,7 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; import org.hisp.dhis.category.CategoryService; import org.hisp.dhis.common.AnalyticalObjectStore; @@ -2551,7 +2552,7 @@ void dataValueAuditMergeDeleteTest() throws ConflictException { } // -------------------------------------- - // -- TrackedEntityDataValueChangeLog -- + // -- EventChangeLog -- // -------------------------------------- @Test @DisplayName( @@ -2671,7 +2672,7 @@ private DataValueAudit createDataValueAudit(DataElement de, String value, Period DataValueAudit dva = new DataValueAudit(); dva.setDataElement(de); dva.setValue(value); - dva.setAuditType(CREATE); + dva.setAuditType(AuditOperationType.CREATE); dva.setCreated(new Date()); dva.setCategoryOptionCombo(coc1); dva.setAttributeOptionCombo(coc1); diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/query/QueryServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/query/QueryServiceTest.java index 8a401834d99c..d6a5715a8f86 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/query/QueryServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/query/QueryServiceTest.java @@ -39,8 +39,6 @@ import java.util.Date; import java.util.List; import java.util.stream.Collectors; -import org.hibernate.Session; -import org.hibernate.stat.Statistics; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.common.ValueType; @@ -597,22 +595,8 @@ void testCriteriaAndRootJunctionDEG() { query.add(Restrictions.eq("dataElements.id", "deabcdefghD")); query.add(Restrictions.eq("dataElements.id", "deabcdefghE")); query.add(Restrictions.eq("dataElements.id", "deabcdefghF")); - Session session = entityManager.unwrap(Session.class); - Statistics statistics = session.getSessionFactory().getStatistics(); - statistics.setStatisticsEnabled(true); - List objects = queryService.query(query); - String[] queries = statistics.getQueries(); - boolean findQuery = false; - for (String q : queries) { - if (q.equals( - "select generatedAlias0 from DataElementGroup as generatedAlias0 inner join generatedAlias0.members as members where ( members.uid=:param0 ) and ( members.uid=:param1 ) and ( members.uid=:param2 ) and ( members.uid=:param3 ) and ( members.uid=:param4 ) and ( members.uid=:param5 )")) { - findQuery = true; - break; - } - } - assertTrue(findQuery); + List objects = queryService.query(query); assertTrue(objects.isEmpty()); - statistics.setStatisticsEnabled(false); } @Test diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/trackedentity/TrackedEntityAuditStoreTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/trackedentity/TrackedEntityAuditStoreTest.java index 7091e82c6703..7cbbf31028aa 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/trackedentity/TrackedEntityAuditStoreTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/trackedentity/TrackedEntityAuditStoreTest.java @@ -33,7 +33,7 @@ import java.util.Date; import java.util.List; -import org.hisp.dhis.changelog.ChangeLogType; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.test.integration.PostgresIntegrationTestBase; import org.hisp.dhis.tracker.audit.TrackedEntityAuditStore; import org.junit.jupiter.api.Test; @@ -53,13 +53,13 @@ class TrackedEntityAuditStoreTest extends PostgresIntegrationTestBase { @Autowired private TrackedEntityAuditStore store; private final TrackedEntityAudit auditA = - new TrackedEntityAudit("WGW7UnVcIIb", "Access", created, "userA", ChangeLogType.CREATE); + new TrackedEntityAudit("WGW7UnVcIIb", "Access", created, "userA", AuditOperationType.CREATE); private final TrackedEntityAudit auditB = - new TrackedEntityAudit("WGW7UnVcIIb", "Access", created, "userB", ChangeLogType.UPDATE); + new TrackedEntityAudit("WGW7UnVcIIb", "Access", created, "userB", AuditOperationType.UPDATE); private final TrackedEntityAudit auditC = - new TrackedEntityAudit("zIAwTY3Drrn", "Access", created, "userA", ChangeLogType.UPDATE); + new TrackedEntityAudit("zIAwTY3Drrn", "Access", created, "userA", AuditOperationType.UPDATE); private final TrackedEntityAudit auditD = - new TrackedEntityAudit("zIAwTY3Drrn", "Access", created, "userB", ChangeLogType.DELETE); + new TrackedEntityAudit("zIAwTY3Drrn", "Access", created, "userB", AuditOperationType.DELETE); @Test void shouldAuditTrackedEntity_whenAddAuditList() { @@ -73,13 +73,14 @@ void shouldAuditTrackedEntity_whenAddAuditList() { List trackedEntityAudits = store.getTrackedEntityAudit(params); assertEquals(trackedEntityAuditInput.size(), trackedEntityAudits.size()); - TrackedEntityAudit entityAudit = filterByAuditType(trackedEntityAudits, ChangeLogType.CREATE); + TrackedEntityAudit entityAudit = + filterByAuditType(trackedEntityAudits, AuditOperationType.CREATE); assertNotNull(entityAudit); assertEquals("userA", entityAudit.getAccessedBy()); assertEquals("WGW7UnVcIIb", entityAudit.getTrackedEntity()); - entityAudit = filterByAuditType(trackedEntityAudits, ChangeLogType.UPDATE); + entityAudit = filterByAuditType(trackedEntityAudits, AuditOperationType.UPDATE); assertNotNull(entityAudit); assertEquals("userB", entityAudit.getAccessedBy()); @@ -87,9 +88,9 @@ void shouldAuditTrackedEntity_whenAddAuditList() { } private static TrackedEntityAudit filterByAuditType( - List trackedEntityAuditsStore, ChangeLogType changeLogType) { + List trackedEntityAuditsStore, AuditOperationType auditOperationType) { return trackedEntityAuditsStore.stream() - .filter(a -> a.getAuditType() == changeLogType) + .filter(a -> a.getAuditType() == auditOperationType) .findFirst() .orElse(null); } @@ -111,13 +112,13 @@ void testGetAuditsByParams() { assertContainsOnly(List.of(auditA, auditC), store.getTrackedEntityAudit(params)); - params = new TrackedEntityAuditQueryParams().setAuditTypes(List.of(ChangeLogType.UPDATE)); + params = new TrackedEntityAuditQueryParams().setAuditTypes(List.of(AuditOperationType.UPDATE)); assertContainsOnly(List.of(auditB, auditC), store.getTrackedEntityAudit(params)); params = new TrackedEntityAuditQueryParams() - .setAuditTypes(List.of(ChangeLogType.CREATE, ChangeLogType.DELETE)); + .setAuditTypes(List.of(AuditOperationType.CREATE, AuditOperationType.DELETE)); assertContainsOnly(List.of(auditA, auditD), store.getTrackedEntityAudit(params)); diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/deduplication/DeduplicationServiceMergeIntegrationTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/deduplication/DeduplicationServiceMergeIntegrationTest.java index be754024a34a..7c68b06d6797 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/deduplication/DeduplicationServiceMergeIntegrationTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/deduplication/DeduplicationServiceMergeIntegrationTest.java @@ -28,6 +28,7 @@ package org.hisp.dhis.tracker.deduplication; import static java.util.Objects.requireNonNull; +import static org.hisp.dhis.changelog.ChangeLogType.CREATE; import static org.hisp.dhis.changelog.ChangeLogType.UPDATE; import static org.hisp.dhis.security.Authorities.ALL; import static org.hisp.dhis.test.utils.Assertions.assertIsEmpty; @@ -43,7 +44,6 @@ import java.util.Map; import java.util.Set; import org.hisp.dhis.analytics.AggregationType; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.common.UID; import org.hisp.dhis.common.ValueType; @@ -384,7 +384,7 @@ private void assertChangeLogCreate(List trackedEntityCha assertNotEmpty(trackedEntityChangeLogs); assertEquals(original.getUid(), trackedEntityChangeLogs.get(0).getTrackedEntity().getUid()); assertEquals("value", trackedEntityChangeLogs.get(0).getCurrentValue()); - assertEquals(ChangeLogType.CREATE, trackedEntityChangeLogs.get(0).getChangeLogType()); + assertEquals(CREATE, trackedEntityChangeLogs.get(0).getChangeLogType()); } private void assertChangeLogUpdate( diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java index 671da213c93d..d797b3ccf943 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/trackedentity/TrackedEntityServiceTest.java @@ -161,6 +161,8 @@ class TrackedEntityServiceTest extends PostgresIntegrationTestBase { private Enrollment enrollmentB; + private ProgramStage programStageA1; + private Event eventA; private Event eventB; @@ -173,8 +175,6 @@ class TrackedEntityServiceTest extends PostgresIntegrationTestBase { private TrackedEntity trackedEntityGrandchildA; - private Note note; - private CategoryOptionCombo defaultCategoryOptionCombo; private Relationship relationshipA; @@ -270,7 +270,7 @@ void setUp() { programA.setCategoryCombo(defaultCategoryCombo); programA.setMinAttributesRequiredToSearch(0); manager.save(programA, false); - ProgramStage programStageA1 = createProgramStage(programA); + programStageA1 = createProgramStage(programA); programStageA1.setPublicAccess(AccessStringHelper.FULL); manager.save(programStageA1, false); ProgramStage programStageA2 = createProgramStage(programA); @@ -360,7 +360,7 @@ void setUp() { eventA.setCompletedDate(parseDate("2021-02-27T11:05:00.000")); eventA.setCompletedBy("herb"); eventA.setAssignedUser(user); - note = new Note("note1", "ant"); + Note note = new Note("note1", "ant"); note.setUid(generateUid()); note.setCreated(new Date()); note.setLastUpdated(new Date()); @@ -1342,6 +1342,37 @@ void shouldReturnTrackedEntityWithoutEventsGivenTheyShouldNotBeIncluded() assertIsEmpty(enrollmentA.get().getEvents()); } + @Test + void shouldReturnTrackedEntityWithoutEventWhenProgramStageNotAccessible() + throws ForbiddenException, BadRequestException, NotFoundException { + injectAdminIntoSecurityContext(); + programStageA1.setSharing(Sharing.builder().publicAccess("--------").build()); + manager.update(programStageA1); + injectSecurityContextUser(user); + TrackedEntityParams params = new TrackedEntityParams(false, TRUE, true, false); + TrackedEntityOperationParams operationParams = + TrackedEntityOperationParams.builder() + .organisationUnits(orgUnitA) + .orgUnitMode(SELECTED) + .trackedEntityType(trackedEntityTypeA) + .trackedEntities(trackedEntityA) + .trackedEntityParams(params) + .build(); + + List trackedEntities = trackedEntityService.getTrackedEntities(operationParams); + + assertContainsOnly(List.of(trackedEntityA), trackedEntities); + assertContainsOnly( + Set.of(enrollmentA.getUid(), enrollmentB.getUid()), + uids(trackedEntities.get(0).getEnrollments())); + List enrollments = new ArrayList<>(trackedEntities.get(0).getEnrollments()); + Optional enrollmentA = + enrollments.stream() + .filter(enrollment -> enrollment.getUid().equals(this.enrollmentA.getUid())) + .findFirst(); + assertIsEmpty(enrollmentA.get().getEvents()); + } + @Test void shouldReturnTrackedEntityMappedCorrectly() throws ForbiddenException, NotFoundException, BadRequestException { @@ -2023,6 +2054,55 @@ void shouldReturnTrackedEntityTypeAttributesWhenSingleTERequestedAndNoProgramSpe UID.of(trackedEntityA), UID.of(programA), TrackedEntityParams.TRUE)); } + @Test + void shouldFindTrackedEntityWithEventsWhenEventRequestedAndAccessible() + throws ForbiddenException, NotFoundException, BadRequestException { + injectAdminIntoSecurityContext(); + User testUser = createAndAddUser(false, "testUser", emptySet(), emptySet(), "F_EXPORT_DATA"); + testUser.setOrganisationUnits(Set.of(orgUnitA)); + manager.update(testUser); + injectSecurityContext(UserDetails.fromUser(testUser)); + + TrackedEntity trackedEntity = + trackedEntityService.getTrackedEntity( + UID.of(trackedEntityA), UID.of(programA), TrackedEntityParams.TRUE); + + assertEquals(trackedEntityA.getUid(), trackedEntity.getUid()); + assertContainsOnly(Set.of(enrollmentA.getUid()), uids(trackedEntity.getEnrollments())); + List enrollments = new ArrayList<>(trackedEntity.getEnrollments()); + Optional enrollmentA = + enrollments.stream() + .filter(enrollment -> enrollment.getUid().equals(this.enrollmentA.getUid())) + .findFirst(); + Set events = enrollmentA.get().getEvents(); + assertContainsOnly(Set.of(eventA.getUid()), uids(events)); + } + + @Test + void shouldFindTrackedEntityWithoutEventsWhenEventRequestedButNotAccessible() + throws ForbiddenException, NotFoundException, BadRequestException { + injectAdminIntoSecurityContext(); + programStageA1.setSharing(Sharing.builder().publicAccess("--------").build()); + manager.update(programStageA1); + User testUser = createAndAddUser(false, "testUser", emptySet(), emptySet(), "F_EXPORT_DATA"); + testUser.setOrganisationUnits(Set.of(orgUnitA)); + manager.update(testUser); + injectSecurityContext(UserDetails.fromUser(testUser)); + + TrackedEntity trackedEntity = + trackedEntityService.getTrackedEntity( + UID.of(trackedEntityA), UID.of(programA), TrackedEntityParams.TRUE); + + assertEquals(trackedEntityA.getUid(), trackedEntity.getUid()); + assertContainsOnly(Set.of(enrollmentA.getUid()), uids(trackedEntity.getEnrollments())); + List enrollments = new ArrayList<>(trackedEntity.getEnrollments()); + Optional enrollmentA = + enrollments.stream() + .filter(enrollment -> enrollment.getUid().equals(this.enrollmentA.getUid())) + .findFirst(); + assertIsEmpty(enrollmentA.get().getEvents()); + } + private Set attributeNames(final Collection attributes) { // depends on createTrackedEntityAttribute() prefixing with "Attribute" return attributes.stream() diff --git a/dhis-2/dhis-test-web-api/pom.xml b/dhis-2/dhis-test-web-api/pom.xml index ac54aae39485..8589e77aff19 100644 --- a/dhis-2/dhis-test-web-api/pom.xml +++ b/dhis-2/dhis-test-web-api/pom.xml @@ -157,16 +157,6 @@ spring-webmvc test - - jakarta.persistence - jakarta.persistence-api - test - - - org.hibernate - hibernate-core-jakarta - test - org.slf4j slf4j-api diff --git a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/OptionControllerTest.java b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/OptionControllerTest.java index 49fd8b49213d..116770a383d2 100644 --- a/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/OptionControllerTest.java +++ b/dhis-2/dhis-test-web-api/src/test/java/org/hisp/dhis/webapi/controller/OptionControllerTest.java @@ -31,8 +31,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.List; -import org.hibernate.Session; -import org.hibernate.stat.Statistics; import org.hisp.dhis.http.HttpStatus; import org.hisp.dhis.jsontree.JsonObject; import org.hisp.dhis.test.webapi.H2ControllerIntegrationTestBase; @@ -142,40 +140,4 @@ void testOptionSetsWithDescription() { List.of("this-is-a", "this-is-b"), set.getOptions().toList(JsonIdentifiableObject::getDescription)); } - - @Test - void testQueryOptionsByOptionSetIds() { - Session session = entityManager.unwrap(Session.class); - - String id = - assertStatus( - HttpStatus.CREATED, - POST( - "/optionSets/", - "{'name': 'test', 'version': 2, 'valueType': 'TEXT', 'description':'desc' }")); - assertStatus( - HttpStatus.CREATED, - POST( - "/options/", - "{'optionSet': { 'id':'" - + id - + "'}, 'id':'Uh4HvjK6zg3', 'code': 'A', 'name': 'Anna', 'description': 'this-is-a'}")); - assertStatus( - HttpStatus.CREATED, - POST( - "/options/", - "{'optionSet': { 'id':'" - + id - + "'},'id':'BQMei56UBl6','code': 'B', 'name': 'Betta', 'description': 'this-is-b'}")); - Statistics statistics = session.getSessionFactory().getStatistics(); - statistics.setStatisticsEnabled(true); - assertEquals(0, statistics.getQueryExecutionCount()); - JsonOptionSet set = - GET(String.format("/options?filter=optionSet.id:in:[%s,%s]", id, "TESTUIDA")) - .content() - .as(JsonOptionSet.class); - assertEquals(2, statistics.getQueryExecutionCount()); - assertEquals(2, set.getOptions().size()); - statistics.setStatisticsEnabled(false); - } } diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AuditController.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AuditController.java index cff31f133131..dcbe7d2fd270 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AuditController.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AuditController.java @@ -43,8 +43,8 @@ import java.util.Set; import lombok.RequiredArgsConstructor; import org.hisp.dhis.audit.Audit; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.DhisApiVersion; import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.common.OpenApi; @@ -174,7 +174,7 @@ public RootNode getAggregateDataValueAudit( String co, @OpenApi.Param({UID.class, CategoryOptionCombo.class}) @RequestParam(required = false) String cc, - @RequestParam(required = false) List auditType, + @RequestParam(required = false) List auditType, @RequestParam(required = false) Boolean skipPaging, @RequestParam(required = false) Boolean paging, @RequestParam(required = false, defaultValue = "50") int pageSize, @@ -194,7 +194,7 @@ public RootNode getAggregateDataValueAudit( List organisationUnits = manager.loadByUid(OrganisationUnit.class, ou); CategoryOptionCombo categoryOptionCombo = manager.get(CategoryOptionCombo.class, co); CategoryOptionCombo attributeOptionCombo = manager.get(CategoryOptionCombo.class, cc); - List changeLogTypes = emptyIfNull(auditType); + List auditOperationTypes = emptyIfNull(auditType); DataValueAuditQueryParams params = new DataValueAuditQueryParams() @@ -203,7 +203,7 @@ public RootNode getAggregateDataValueAudit( .setOrgUnits(organisationUnits) .setCategoryOptionCombo(categoryOptionCombo) .setAttributeOptionCombo(attributeOptionCombo) - .setAuditTypes(changeLogTypes); + .setAuditTypes(auditOperationTypes); List dataValueAudits; Pager pager = null; @@ -223,7 +223,7 @@ public RootNode getAggregateDataValueAudit( .setOrgUnits(organisationUnits) .setCategoryOptionCombo(categoryOptionCombo) .setAttributeOptionCombo(attributeOptionCombo) - .setAuditTypes(changeLogTypes) + .setAuditTypes(auditOperationTypes) .setPager(pager)); } @@ -314,7 +314,7 @@ public RootNode getTrackedEntityInstanceAudit( @RequestParam(required = false, defaultValue = "") Set trackedEntities, @OpenApi.Param({UID[].class, User.class}) @RequestParam(required = false) List user, - @RequestParam(required = false) List auditType, + @RequestParam(required = false) List auditType, @RequestParam(required = false) Date startDate, @RequestParam(required = false) Date endDate, @RequestParam(required = false) Boolean skipPaging, @@ -328,7 +328,7 @@ public RootNode getTrackedEntityInstanceAudit( fields.addAll(FieldPreset.ALL.getFields()); } - List changeLogTypes = emptyIfNull(auditType); + List auditOperationTypes = emptyIfNull(auditType); Set teUids = validateDeprecatedUidsParameter( @@ -338,7 +338,7 @@ public RootNode getTrackedEntityInstanceAudit( new TrackedEntityAuditQueryParams() .setTrackedEntities(UID.toValueList(teUids)) .setUsers(user) - .setAuditTypes(changeLogTypes) + .setAuditTypes(auditOperationTypes) .setStartDate(startDate) .setEndDate(endDate); @@ -377,7 +377,7 @@ public RootNode getTrackedEntityAudit( @RequestParam(required = false, defaultValue = "") Set trackedEntities, @OpenApi.Param({UID[].class, User.class}) @RequestParam(required = false) List user, - @RequestParam(required = false) List auditType, + @RequestParam(required = false) List auditType, @RequestParam(required = false) Date startDate, @RequestParam(required = false) Date endDate, @RequestParam(required = false) Boolean skipPaging, @@ -390,13 +390,13 @@ public RootNode getTrackedEntityAudit( fields.addAll(FieldPreset.ALL.getFields()); } - List changeLogTypes = emptyIfNull(auditType); + List auditOperationTypes = emptyIfNull(auditType); TrackedEntityAuditQueryParams params = new TrackedEntityAuditQueryParams() .setTrackedEntities(UID.toValueList(trackedEntities)) .setUsers(user) - .setAuditTypes(changeLogTypes) + .setAuditTypes(auditOperationTypes) .setStartDate(startDate) .setEndDate(endDate); diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java index fa0c1d28d262..d069db69b730 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/MessageConversationController.java @@ -180,8 +180,11 @@ public ResponseEntity getObject( @Override protected List getPreQueryMatches(GetMessageConversationObjectListParams params) { + if (params.getQuery() != null) return null; + List allUserMessages = + messageService.getMessageConversations(); String query = params.getQueryString(); - if (query == null) return null; + if (query == null) return allUserMessages.stream().map(UID::of).toList(); String op = params.getQueryOperator(); if (op == null) op = "token"; @@ -197,7 +200,8 @@ protected List getPreQueryMatches(GetMessageConversationObjectListParams pa .setPaging(false) .setRootJunction(Junction.Type.OR) .setFilters(filters); - Query subQuery = queryService.getQueryFromUrl(getEntityClass(), subQueryParams); + Query subQuery = + queryService.getQueryFromUrl(getEntityClass(), subQueryParams).setObjects(allUserMessages); // Note: in theory these filters could be added to the main query // but the OR concerns both DB and in-memory properties // which would break if added to the main query ATM diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/event/EventsExportController.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/event/EventsExportController.java index 10e2b59cf7c4..22587faa0276 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/event/EventsExportController.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/event/EventsExportController.java @@ -363,6 +363,7 @@ ResponseEntity getEventDataValueImage( request, eventService.getFileResourceImage(event, dataElement, dimension)); } + @OpenApi.Response(status = Status.OK, value = Page.class) @GetMapping("/{event}/changeLogs") ResponseEntity> getEventChangeLogsByUid( @OpenApi.Param({UID.class, Event.class}) @PathVariable UID event, diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/trackedentity/TrackedEntitiesExportController.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/trackedentity/TrackedEntitiesExportController.java index e57977c33f59..182c73e63a3b 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/trackedentity/TrackedEntitiesExportController.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/tracker/export/trackedentity/TrackedEntitiesExportController.java @@ -351,8 +351,9 @@ ResponseEntity getAttributeValueImage( trackedEntityService.getFileResourceImage(trackedEntity, attribute, program, dimension)); } + @OpenApi.Response(status = Status.OK, value = Page.class) @GetMapping("/{trackedEntity}/changeLogs") - ResponseEntity> getTrackedEntityAttributeChangeLog( + ResponseEntity> getTrackedEntityChangeLog( @OpenApi.Param({UID.class, org.hisp.dhis.trackedentity.TrackedEntity.class}) @PathVariable UID trackedEntity, @OpenApi.Param({UID.class, Program.class}) @RequestParam(required = false) UID program, diff --git a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/webdomain/datavalue/DataValueAuditDto.java b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/webdomain/datavalue/DataValueAuditDto.java index 30d2c5eb2897..d48c386d3a82 100644 --- a/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/webdomain/datavalue/DataValueAuditDto.java +++ b/dhis-2/dhis-web-api/src/main/java/org/hisp/dhis/webapi/webdomain/datavalue/DataValueAuditDto.java @@ -33,8 +33,8 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; +import org.hisp.dhis.audit.AuditOperationType; import org.hisp.dhis.category.CategoryOptionCombo; -import org.hisp.dhis.changelog.ChangeLogType; import org.hisp.dhis.common.OpenApi; import org.hisp.dhis.common.UID; import org.hisp.dhis.dataelement.DataElement; @@ -77,5 +77,5 @@ public class DataValueAuditDto { @JsonProperty private Date created; - @JsonProperty private ChangeLogType auditType; + @JsonProperty private AuditOperationType auditType; } diff --git a/dhis-2/pom.xml b/dhis-2/pom.xml index 7c62f28ec858..65d82d92c00e 100644 --- a/dhis-2/pom.xml +++ b/dhis-2/pom.xml @@ -205,7 +205,7 @@ 1.3.20 - 1.14.0 + 1.14.2 1.3.1