From 226fa113c06499459b35d0812c4b51db08402938 Mon Sep 17 00:00:00 2001 From: Maikel Arabori <51713408+maikelarabori@users.noreply.github.com> Date: Thu, 21 Nov 2024 14:31:07 +0100 Subject: [PATCH] fix: Order of relative periods in analytics models [DHIS2-18020] (#19253) --- .../dhis/common/BaseAnalyticalObject.java | 86 ++++-- .../java/org/hisp/dhis/period/Period.java | 14 + .../java/org/hisp/dhis/report/Report.java | 46 ++- .../java/org/hisp/dhis/report/ReportTest.java | 95 ++++++ .../dimension/DefaultDimensionService.java | 16 +- .../eventchart/hibernate/EventChart.hbm.xml | 6 +- .../eventreport/hibernate/EventReport.hbm.xml | 6 +- .../hibernate/EventVisualization.hbm.xml | 6 +- .../dhis/mapping/hibernate/MapView.hbm.xml | 5 +- .../hisp/dhis/report/hibernate/Report.hbm.xml | 5 +- .../hibernate/Visualization.hbm.xml | 3 +- .../DefaultAnalyticalObjectImportHandler.java | 51 ++++ ...lization_and_migrate_relative_periods.java | 274 ++++++++++++++++++ .../dhis/dimension/DimensionServiceTest.java | 53 ++++ 14 files changed, 607 insertions(+), 59 deletions(-) create mode 100644 dhis-2/dhis-api/src/test/java/org/hisp/dhis/report/ReportTest.java create mode 100644 dhis-2/dhis-support/dhis-support-db-migration/src/main/java/org/hisp/dhis/db/migration/v39/V2_39_30__Add_new_column_into_visualization_and_migrate_relative_periods.java diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java index b4016be96464..146c58cac563 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java @@ -87,7 +87,6 @@ import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.organisationunit.OrganisationUnitGroup; import org.hisp.dhis.organisationunit.OrganisationUnitGroupSetDimension; -import org.hisp.dhis.period.ConfigurablePeriod; import org.hisp.dhis.period.Period; import org.hisp.dhis.period.RelativePeriodEnum; import org.hisp.dhis.period.RelativePeriods; @@ -139,6 +138,8 @@ public abstract class BaseAnalyticalObject extends BaseNameableObject implements protected RelativePeriods relatives; + protected List rawRelativePeriods = new ArrayList<>(); + protected List dataElementGroupSetDimensions = new ArrayList<>(); protected List organisationUnitGroupSetDimensions = @@ -250,7 +251,7 @@ public boolean hasUserOrgUnit() { } public boolean hasRelativePeriods() { - return relatives != null && !relatives.isEmpty(); + return rawRelativePeriods != null && !rawRelativePeriods.isEmpty(); } public boolean hasOrganisationUnitLevels() { @@ -515,15 +516,13 @@ protected DimensionalObject getDimensionalObject( * @return the dimensional object related to the given dimension and attribute. */ protected DimensionalObject getDimensionalObject( - final EventAnalyticalObject eventAnalyticalObject, - final String dimension, - final Attribute parent) { - final Optional optionalDimensionalObject = getDimensionalObject(dimension); + EventAnalyticalObject eventAnalyticalObject, String dimension, Attribute parent) { + Optional optionalDimensionalObject = getDimensionalObject(dimension); if (optionalDimensionalObject.isPresent()) { return linkAssociations(eventAnalyticalObject, optionalDimensionalObject.get(), parent); } else if (Type.contains(dimension)) { - final DimensionalObject dimensionalObject = + DimensionalObject dimensionalObject = new SimpleDimensionHandler(eventAnalyticalObject).getDimensionalObject(dimension, parent); return linkAssociations(eventAnalyticalObject, dimensionalObject, parent); @@ -542,14 +541,14 @@ protected DimensionalObject getDimensionalObject( * @return the dimensional object containing the correct associations. */ private DimensionalObject linkAssociations( - final EventAnalyticalObject eventAnalyticalObject, - final DimensionalObject dimensionalObject, - final Attribute parent) { + EventAnalyticalObject eventAnalyticalObject, + DimensionalObject dimensionalObject, + Attribute parent) { // Associating event repetitions. - final List repetitions = eventAnalyticalObject.getEventRepetitions(); + List repetitions = eventAnalyticalObject.getEventRepetitions(); if (isNotEmpty(repetitions)) { - for (final EventRepetition eventRepetition : repetitions) { + for (EventRepetition eventRepetition : repetitions) { if (eventRepetition.getDimension() != null && eventRepetition.getDimension().equals(dimensionalObject.getDimension()) && parent == eventRepetition.getParent()) { @@ -568,11 +567,11 @@ private DimensionalObject linkAssociations( * @param dimensionalObjects */ protected void populateDimensions( - final List dimensions, final List dimensionalObjects) { + List dimensions, List dimensionalObjects) { if (isNotEmpty(dimensions)) { - for (final String dimension : dimensions) { + for (String dimension : dimensions) { if (isNotBlank(dimension)) { - final Optional dimensionalObject = getDimensionalObject(dimension); + Optional dimensionalObject = getDimensionalObject(dimension); if (dimensionalObject.isPresent()) { dimensionalObjects.add(dimensionalObject.get()); } @@ -589,12 +588,12 @@ protected void populateDimensions( * @param dimensionalObjects */ protected void populateDimensions( - final List dimensions, - final List dimensionalObjects, - final Attribute attribute, - final EventAnalyticalObject eventAnalyticalObject) { + List dimensions, + List dimensionalObjects, + Attribute attribute, + EventAnalyticalObject eventAnalyticalObject) { if (isNotEmpty(dimensions)) { - for (final String dimension : dimensions) { + for (String dimension : dimensions) { if (isNotBlank(dimension)) { dimensionalObjects.add(getDimensionalObject(eventAnalyticalObject, dimension, attribute)); } @@ -625,10 +624,8 @@ protected Optional getDimensionalObject(String dimension) { List periodList = new ArrayList<>(periods); if (hasRelativePeriods()) { - List list = relatives.getRelativePeriodEnums(); - - for (RelativePeriodEnum periodEnum : list) { - periodList.add(new ConfigurablePeriod(periodEnum.toString())); + for (String relPeriod : rawRelativePeriods) { + periodList.add(new Period(RelativePeriodEnum.valueOf(relPeriod))); } } @@ -718,12 +715,13 @@ private Optional getTrackedEntityDimension(String dimension) .collect(toMap(TrackedEntityAttributeDimension::getUid, Function.identity())); if (attributes.containsKey(dimension)) { - final TrackedEntityAttributeDimension tead = attributes.get(dimension); + TrackedEntityAttributeDimension tead = attributes.get(dimension); if (tead != null) { - final ValueType valueType = + ValueType valueType = tead.getAttribute() != null ? tead.getAttribute().getValueType() : null; - final OptionSet optionSet = + + OptionSet optionSet = tead.getAttribute() != null ? tead.getAttribute().getOptionSet() : null; return Optional.of( @@ -777,7 +775,7 @@ private Optional getTrackedEntityDimension(String dimension) .collect(toMap(TrackedEntityProgramIndicatorDimension::getUid, Function.identity())); if (programIndicators.containsKey(dimension)) { - final TrackedEntityProgramIndicatorDimension teid = programIndicators.get(dimension); + TrackedEntityProgramIndicatorDimension teid = programIndicators.get(dimension); return Optional.of( new BaseDimensionalObject( @@ -805,11 +803,11 @@ private Optional getTrackedEntityDimension(String dimension) private Optional getDimensionFromEmbeddedObjects( String dimension, DimensionType dimensionType, List embeddedObjects) { - final Map dimensions = + Map dimensions = Maps.uniqueIndex(embeddedObjects, d -> d.getDimension().getDimension()); if (dimensions.containsKey(dimension)) { - final DimensionalEmbeddedObject object = dimensions.get(dimension); + DimensionalEmbeddedObject object = dimensions.get(dimension); if (object != null) { return Optional.of( @@ -835,7 +833,7 @@ private void setPeriodNames(List periods, boolean dynamicNames, I18nForm * dynamic dimensions. */ public Map getMetaData() { - final Map meta = new HashMap<>(); + Map meta = new HashMap<>(); // TODO use getDimension() instead of getUid() ? dataElementGroupSetDimensions.forEach( @@ -934,6 +932,20 @@ public void setEndDate(Date endDate) { @JsonProperty(value = "relativePeriods") @JacksonXmlProperty(localName = "relativePeriods", namespace = DxfNamespaces.DXF_2_0) public RelativePeriods getRelatives() { + if (relatives == null) { + List enums = new ArrayList<>(); + + if (rawRelativePeriods != null) { + for (String relativePeriod : rawRelativePeriods) { + if (RelativePeriodEnum.contains(relativePeriod)) { + enums.add(RelativePeriodEnum.valueOf(relativePeriod)); + } + } + } + + return new RelativePeriods().setRelativePeriodsFromEnums(enums); + } + return relatives; } @@ -941,6 +953,18 @@ public void setRelatives(RelativePeriods relatives) { this.relatives = relatives; } + @JsonProperty + @JsonIgnore + @JacksonXmlElementWrapper(localName = "rawRelativePeriods", namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlProperty(localName = "rawRelativePeriods", namespace = DxfNamespaces.DXF_2_0) + public List getRawRelativePeriods() { + return rawRelativePeriods; + } + + public void setRawRelativePeriods(List rawRelativePeriods) { + this.rawRelativePeriods = rawRelativePeriods; + } + @JsonProperty @JacksonXmlElementWrapper( localName = "dataElementGroupSetDimensions", diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Period.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Period.java index ac31a38aa78e..10b8d6cbd9e5 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Period.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/period/Period.java @@ -113,6 +113,20 @@ public Period(Period period) { this.dateField = period.getDateField(); } + /** + * Creates a period that is not bound to the persistent layer. It represents a detached Period + * that is mainly used for displaying purposes. + * + * @param isoRelativePeriod the ISO relative period + */ + public Period(RelativePeriodEnum isoRelativePeriod) { + this.isoPeriod = isoRelativePeriod.toString(); + this.name = isoRelativePeriod.toString(); + this.code = isoRelativePeriod.toString(); + this.setStartDate(new Date()); + this.setEndDate(new Date()); + } + protected Period(PeriodType periodType, Date startDate, Date endDate) { this.periodType = periodType; this.startDate = startDate; diff --git a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java index 0756cb4634fe..51552f197de8 100644 --- a/dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java +++ b/dhis-2/dhis-api/src/main/java/org/hisp/dhis/report/Report.java @@ -33,10 +33,13 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; +import java.util.ArrayList; +import java.util.List; import org.hisp.dhis.common.BaseIdentifiableObject; import org.hisp.dhis.common.MetadataObject; import org.hisp.dhis.common.cache.CacheStrategy; import org.hisp.dhis.common.cache.Cacheable; +import org.hisp.dhis.period.RelativePeriodEnum; import org.hisp.dhis.period.RelativePeriods; import org.hisp.dhis.schema.annotation.Gist; import org.hisp.dhis.schema.annotation.Gist.Include; @@ -56,6 +59,8 @@ public class Report extends BaseIdentifiableObject implements Cacheable, Metadat private RelativePeriods relatives; + private List rawRelativePeriods = new ArrayList<>(); + private ReportingParams reportingParams; private CacheStrategy cacheStrategy = CacheStrategy.RESPECT_SYSTEM_SETTING; @@ -155,11 +160,50 @@ public void setVisualization(Visualization visualization) { @JsonProperty("relativePeriods") @JacksonXmlProperty(namespace = DXF_2_0) public RelativePeriods getRelatives() { + if (relatives == null) { + List enums = new ArrayList<>(); + + if (rawRelativePeriods != null) { + for (String relativePeriod : rawRelativePeriods) { + if (RelativePeriodEnum.contains(relativePeriod)) { + enums.add(RelativePeriodEnum.valueOf(relativePeriod)); + } + } + } + + return new RelativePeriods().setRelativePeriodsFromEnums(enums); + } + return relatives; } + /** + * It overrides the rawRelativePeriods with the relative periods provided. This is done for + * backward compatibility reasons. + * + * @param relatives the {@link RelativePeriods}. + */ public void setRelatives(RelativePeriods relatives) { - this.relatives = relatives; + if (relatives != null) { + List enums = relatives.getRelativePeriodEnums(); + + for (RelativePeriodEnum periodEnum : enums) { + String relativePeriod = periodEnum.name(); + if (RelativePeriodEnum.contains(relativePeriod)) { + this.rawRelativePeriods.add(relativePeriod); + } + } + + this.relatives = relatives; + } + } + + public List getRawRelativePeriods() { + return rawRelativePeriods; + } + + public void setRawRelativePeriods(List rawRelativePeriods) { + this.rawRelativePeriods = rawRelativePeriods; } @JsonProperty diff --git a/dhis-2/dhis-api/src/test/java/org/hisp/dhis/report/ReportTest.java b/dhis-2/dhis-api/src/test/java/org/hisp/dhis/report/ReportTest.java new file mode 100644 index 000000000000..4f768c9bfaaf --- /dev/null +++ b/dhis-2/dhis-api/src/test/java/org/hisp/dhis/report/ReportTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2004-2024, 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.report; + +import static org.hisp.dhis.period.RelativePeriodEnum.BIMONTHS_THIS_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_14_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_3_MONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_7_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_BIWEEK; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import org.hisp.dhis.period.RelativePeriods; +import org.junit.jupiter.api.Test; + +/** Unit tests for {@link Report}. */ +class ReportTest { + @Test + void testGetRelatives() { + // Given + List rawRelativePeriods = + List.of(BIMONTHS_THIS_YEAR.name(), THIS_BIWEEK.name(), LAST_7_DAYS.name()); + Report report = new Report(); + report.setRawRelativePeriods(rawRelativePeriods); + // When + RelativePeriods relativePeriods = report.getRelatives(); + // Then + assertTrue(relativePeriods.isBiMonthsThisYear()); + assertTrue(relativePeriods.isThisBiWeek()); + assertTrue(relativePeriods.isLast7Days()); + } + + @Test + void testGetRelativesWhenRawRelativePeriodsIsNull() { + // Given + Report report = new Report(); + report.setRawRelativePeriods(null); + // When + RelativePeriods relativePeriods = report.getRelatives(); + // Then + assertTrue(relativePeriods.isEmpty()); + } + + @Test + void testGetRelativesWhenRawRelativePeriodsIsEmpty() { + // Given + Report report = new Report(); + report.setRawRelativePeriods(List.of()); + // When + RelativePeriods relativePeriods = report.getRelatives(); + // Then + assertTrue(relativePeriods.isEmpty()); + } + + @Test + void testSetRelatives() { + // Given + RelativePeriods relativePeriods = new RelativePeriods(); + relativePeriods.setBiMonthsThisYear(true); + relativePeriods.setLast14Days(true); + relativePeriods.setLast3Months(true); + Report report = new Report(); + // When + report.setRelatives(relativePeriods); + // Then + assertTrue(report.getRawRelativePeriods().contains(BIMONTHS_THIS_YEAR.name())); + assertTrue(report.getRawRelativePeriods().contains(LAST_14_DAYS.name())); + assertTrue(report.getRawRelativePeriods().contains(LAST_3_MONTHS.name())); + } +} diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dimension/DefaultDimensionService.java b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dimension/DefaultDimensionService.java index fbf69aa623c0..e18733d79229 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dimension/DefaultDimensionService.java +++ b/dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dimension/DefaultDimensionService.java @@ -55,6 +55,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -105,7 +106,6 @@ import org.hisp.dhis.period.PeriodService; import org.hisp.dhis.period.PeriodType; import org.hisp.dhis.period.RelativePeriodEnum; -import org.hisp.dhis.period.RelativePeriods; import org.hisp.dhis.program.ProgramDataElementDimensionItem; import org.hisp.dhis.program.ProgramIndicator; import org.hisp.dhis.program.ProgramStage; @@ -513,20 +513,22 @@ private void mergeDimensionalObjects( } else if (PERIOD.equals(type)) { List enums = new ArrayList<>(); List periods = new UniqueArrayList<>(); + Set relativePeriods = new LinkedHashSet<>(); - for (String isoPeriod : uids) { - if (RelativePeriodEnum.contains(isoPeriod)) { - enums.add(RelativePeriodEnum.valueOf(isoPeriod)); + for (String period : uids) { + if (RelativePeriodEnum.contains(period)) { + enums.add(RelativePeriodEnum.valueOf(period)); + relativePeriods.add(period); } else { - Period period = PeriodType.getPeriodFromIsoString(isoPeriod); + Period isoPeriod = PeriodType.getPeriodFromIsoString(period); if (period != null) { - periods.add(period); + periods.add(isoPeriod); } } } - object.setRelatives(new RelativePeriods().setRelativePeriodsFromEnums(enums)); + object.setRawRelativePeriods(new ArrayList<>(relativePeriods)); object.setPeriods(periodService.reloadPeriods(new ArrayList<>(periods))); } else if (ORGANISATION_UNIT.equals(type)) { for (String ou : uids) { diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventchart/hibernate/EventChart.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventchart/hibernate/EventChart.hbm.xml index 08bdff196604..ee0b7350f962 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventchart/hibernate/EventChart.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventchart/hibernate/EventChart.hbm.xml @@ -33,10 +33,6 @@ foreign-key="fk_evisualization_periods_periodid"/> - - @@ -158,6 +154,8 @@ + + diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventreport/hibernate/EventReport.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventreport/hibernate/EventReport.hbm.xml index 6b61a82b3187..877bb608f94e 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventreport/hibernate/EventReport.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventreport/hibernate/EventReport.hbm.xml @@ -33,10 +33,6 @@ foreign-key="fk_evisualization_periods_periodid"/> - - @@ -158,6 +154,8 @@ + + diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventvisualization/hibernate/EventVisualization.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventvisualization/hibernate/EventVisualization.hbm.xml index 57a7f1ca081c..8ab657a2c3a0 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventvisualization/hibernate/EventVisualization.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/eventvisualization/hibernate/EventVisualization.hbm.xml @@ -18,6 +18,8 @@ + + @@ -34,10 +36,6 @@ foreign-key="fk_evisualization_periods_periodid"/> - - diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/mapping/hibernate/MapView.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/mapping/hibernate/MapView.hbm.xml index 8ba175667880..e77a890e9e3f 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/mapping/hibernate/MapView.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/mapping/hibernate/MapView.hbm.xml @@ -47,10 +47,9 @@ - + - + diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/report/hibernate/Report.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/report/hibernate/Report.hbm.xml index 55f093b37860..d1ee4c527166 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/report/hibernate/Report.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/report/hibernate/Report.hbm.xml @@ -29,12 +29,11 @@ + + - - diff --git a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/visualization/hibernate/Visualization.hbm.xml b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/visualization/hibernate/Visualization.hbm.xml index 9049c0529241..a1f47f222b77 100644 --- a/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/visualization/hibernate/Visualization.hbm.xml +++ b/dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/visualization/hibernate/Visualization.hbm.xml @@ -211,8 +211,7 @@ - + diff --git a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultAnalyticalObjectImportHandler.java b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultAnalyticalObjectImportHandler.java index 4ad5f4570490..f88843d014c9 100644 --- a/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultAnalyticalObjectImportHandler.java +++ b/dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultAnalyticalObjectImportHandler.java @@ -27,17 +27,25 @@ */ package org.hisp.dhis.dxf2.metadata; +import static java.util.stream.Collectors.toList; + import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import lombok.RequiredArgsConstructor; import org.hibernate.Session; import org.hisp.dhis.category.CategoryDimension; import org.hisp.dhis.category.CategoryOption; import org.hisp.dhis.common.BaseAnalyticalObject; import org.hisp.dhis.common.DataDimensionItem; +import org.hisp.dhis.common.DimensionalItemObject; +import org.hisp.dhis.common.DimensionalObject; import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundle; import org.hisp.dhis.legend.LegendSet; +import org.hisp.dhis.period.RelativePeriodEnum; +import org.hisp.dhis.period.RelativePeriods; import org.hisp.dhis.preheat.PreheatService; import org.hisp.dhis.schema.Schema; import org.hisp.dhis.trackedentity.TrackedEntityAttributeDimension; @@ -62,6 +70,49 @@ public void handleAnalyticalObject( handleAttributeDimensions(session, schema, analyticalObject, bundle); handleProgramIndicatorDimensions(session, schema, analyticalObject, bundle); handleVisualizationLegendSet(schema, analyticalObject, bundle); + handleRelativePeriods(schema, analyticalObject); + } + + private void handleRelativePeriods(Schema schema, BaseAnalyticalObject analyticalObject) { + if (!schema.havePersistedProperty("rawRelativePeriods")) return; + + Set rawRelativePeriods = new LinkedHashSet<>(); + + addRawRelativesPeriods(analyticalObject.getRows(), rawRelativePeriods); + addRawRelativesPeriods(analyticalObject.getColumns(), rawRelativePeriods); + addRawRelativesPeriods(analyticalObject.getFilters(), rawRelativePeriods); + + RelativePeriods relativePeriods = analyticalObject.getRelatives(); + + if (relativePeriods != null) { + rawRelativePeriods.addAll( + relativePeriods.getRelativePeriodEnums().stream().map(Enum::name).collect(toList())); + } + + analyticalObject.setRawRelativePeriods(new ArrayList<>(rawRelativePeriods)); + } + + /** + * Adds to the Set of periods, the relative periods present in the given list of {@link + * DimensionalObject}, if any. + * + * @param dimObjects the list of {@link DimensionalObject}. + * @param rawRelativePeriods the list of relative periods. + */ + private void addRawRelativesPeriods( + List dimObjects, Set rawRelativePeriods) { + if (dimObjects != null) { + for (DimensionalObject dimObject : dimObjects) { + if (dimObject.hasItems()) { + for (DimensionalItemObject item : dimObject.getItems()) { + String period = item.getUid(); + if (RelativePeriodEnum.contains(period)) { + rawRelativePeriods.add(period); + } + } + } + } + } } /** diff --git a/dhis-2/dhis-support/dhis-support-db-migration/src/main/java/org/hisp/dhis/db/migration/v39/V2_39_30__Add_new_column_into_visualization_and_migrate_relative_periods.java b/dhis-2/dhis-support/dhis-support-db-migration/src/main/java/org/hisp/dhis/db/migration/v39/V2_39_30__Add_new_column_into_visualization_and_migrate_relative_periods.java new file mode 100644 index 000000000000..3759601f0906 --- /dev/null +++ b/dhis-2/dhis-support/dhis-support-db-migration/src/main/java/org/hisp/dhis/db/migration/v39/V2_39_30__Add_new_column_into_visualization_and_migrate_relative_periods.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2004-2024, 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.db.migration.v39; + +import static java.util.stream.Collectors.toList; +import static org.hisp.dhis.period.RelativePeriodEnum.BIMONTHS_THIS_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_10_FINANCIAL_YEARS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_10_YEARS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_12_MONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_12_WEEKS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_14_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_180_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_2_SIXMONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_30_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_3_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_3_MONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_4_BIWEEKS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_4_QUARTERS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_4_WEEKS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_52_WEEKS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_5_FINANCIAL_YEARS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_5_YEARS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_60_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_6_BIMONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_6_MONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_7_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_90_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_BIMONTH; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_BIWEEK; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_FINANCIAL_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_MONTH; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_QUARTER; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_SIX_MONTH; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_WEEK; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.MONTHS_LAST_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.MONTHS_THIS_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.QUARTERS_LAST_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.QUARTERS_THIS_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_BIMONTH; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_BIWEEK; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_FINANCIAL_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_MONTH; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_QUARTER; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_SIX_MONTH; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_WEEK; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.TODAY; +import static org.hisp.dhis.period.RelativePeriodEnum.WEEKS_THIS_YEAR; +import static org.hisp.dhis.period.RelativePeriodEnum.YESTERDAY; +import static org.slf4j.LoggerFactory.getLogger; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.flywaydb.core.api.migration.BaseJavaMigration; +import org.flywaydb.core.api.migration.Context; +import org.postgresql.util.PGobject; +import org.slf4j.Logger; + +public class V2_39_30__Add_new_column_into_visualization_and_migrate_relative_periods + extends BaseJavaMigration { + public static final Map SELECT_UPDATE_PAIRS = + Map.of( + "select v.visualizationid, v.relativeperiodsid from visualization v join relativeperiods r on r.relativeperiodsid = v.relativeperiodsid order by v.visualizationid", + "update visualization set relativeperiods = ? where visualizationid = ?", + "select re.reportid, re.relativeperiodsid from report re join relativeperiods r ON r.relativeperiodsid = re.relativeperiodsid order by re.reportid", + "update report set relativeperiods = ? where reportid = ?", + "select e.eventvisualizationid, e.relativeperiodsid from eventvisualization e join relativeperiods r ON r.relativeperiodsid = e.relativeperiodsid order by e.eventvisualizationid", + "update eventvisualization set relativeperiods = ? where eventvisualizationid = ?", + "select m.mapviewid, m.relativeperiodsid from mapview m join relativeperiods r ON r.relativeperiodsid = m.relativeperiodsid order by m.mapviewid", + "update mapview set relativeperiods = ? where mapviewid = ?"); + private static final Logger log = + getLogger(V2_39_30__Add_new_column_into_visualization_and_migrate_relative_periods.class); + private static final Map PERIODS = new HashMap<>(); + + static { + PERIODS.put("thisDay", TODAY.name()); + PERIODS.put("yesterday", YESTERDAY.name()); + PERIODS.put("last3Days", LAST_3_DAYS.name()); + PERIODS.put("last7Days", LAST_7_DAYS.name()); + PERIODS.put("last14Days", LAST_14_DAYS.name()); + PERIODS.put("last30Days", LAST_30_DAYS.name()); + PERIODS.put("last60Days", LAST_60_DAYS.name()); + PERIODS.put("last90Days", LAST_90_DAYS.name()); + PERIODS.put("last180Days", LAST_180_DAYS.name()); + PERIODS.put("thisMonth", THIS_MONTH.name()); + PERIODS.put("lastMonth", LAST_MONTH.name()); + PERIODS.put("thisBimonth", THIS_BIMONTH.name()); + PERIODS.put("lastBimonth", LAST_BIMONTH.name()); + PERIODS.put("thisQuarter", THIS_QUARTER.name()); + PERIODS.put("lastQuarter", LAST_QUARTER.name()); + PERIODS.put("thisSixMonth", THIS_SIX_MONTH.name()); + PERIODS.put("lastSixMonth", LAST_SIX_MONTH.name()); + PERIODS.put("weeksThisYear", WEEKS_THIS_YEAR.name()); + PERIODS.put("monthsThisYear", MONTHS_THIS_YEAR.name()); + PERIODS.put("biMonthsThisYear", BIMONTHS_THIS_YEAR.name()); + PERIODS.put("quartersThisYear", QUARTERS_THIS_YEAR.name()); + PERIODS.put("thisYear", THIS_YEAR.name()); + PERIODS.put("monthsLastYear", MONTHS_LAST_YEAR.name()); + PERIODS.put("quartersLastYear", QUARTERS_LAST_YEAR.name()); + PERIODS.put("lastYear", LAST_YEAR.name()); + PERIODS.put("last5Years", LAST_5_YEARS.name()); + PERIODS.put("last10Years", LAST_10_YEARS.name()); + PERIODS.put("last12Months", LAST_12_MONTHS.name()); + PERIODS.put("last6Months", LAST_6_MONTHS.name()); + PERIODS.put("last3Months", LAST_3_MONTHS.name()); + PERIODS.put("last6BiMonths", LAST_6_BIMONTHS.name()); + PERIODS.put("last4Quarters", LAST_4_QUARTERS.name()); + PERIODS.put("last2SixMonths", LAST_2_SIXMONTHS.name()); + PERIODS.put("thisFinancialYear", THIS_FINANCIAL_YEAR.name()); + PERIODS.put("lastFinancialYear", LAST_FINANCIAL_YEAR.name()); + PERIODS.put("last5FinancialYears", LAST_5_FINANCIAL_YEARS.name()); + PERIODS.put("last10FinancialYears", LAST_10_FINANCIAL_YEARS.name()); + PERIODS.put("thisWeek", THIS_WEEK.name()); + PERIODS.put("lastWeek", LAST_WEEK.name()); + PERIODS.put("thisBiWeek", THIS_BIWEEK.name()); + PERIODS.put("lastBiWeek", LAST_BIWEEK.name()); + PERIODS.put("last4Weeks", LAST_4_WEEKS.name()); + PERIODS.put("last4BiWeeks", LAST_4_BIWEEKS.name()); + PERIODS.put("last12Weeks", LAST_12_WEEKS.name()); + PERIODS.put("last52Weeks", LAST_52_WEEKS.name()); + } + + public void migrate(Context context) throws SQLException { + if (!isMigrationAlreadyApplied(context)) { + step1(context); + step2(context); + } + } + + private boolean isMigrationAlreadyApplied(Context context) { + String schema = null; + try { + schema = context.getConnection().getSchema(); + } catch (SQLException e) { + log.error("Schema check: ", e); + } + final String checkColumnExists = + "select exists (select 1 from information_schema.columns where " + + (schema != null ? "table_schema='" + schema + "' and " : "") + + "table_name='eventvisualization' and column_name='relativeperiods')"; + try (Statement statement = context.getConnection().createStatement(); + ResultSet rs = statement.executeQuery(checkColumnExists)) { + while (rs.next()) { + return rs.getBoolean(1); + } + } catch (SQLException e) { + log.error("Check failed: ", e); + } + return false; + } + + /** + * Creates the new column "relativeperiods" in all required tables. + * + * @param context + */ + private void step1(Context context) throws SQLException { + try (Statement statement = context.getConnection().createStatement()) { + log.info("Step 1: Add new column 'relativeperiods' into required tables."); + statement.execute( + "alter table if exists visualization add column if not exists relativeperiods jsonb"); + statement.execute( + "alter table if exists report add column if not exists relativeperiods jsonb"); + statement.execute( + "alter table if exists mapview add column if not exists relativeperiods jsonb"); + statement.execute( + "alter table if exists eventvisualization add column if not exists relativeperiods jsonb"); + } catch (SQLException e) { + log.error("Step 1 failed: ", e); + throw e; + } + } + + /** + * Populates the JSON columns based on the existing relative periods table. + * + * @param context + * @throws SQLException + */ + private static void step2(Context context) throws SQLException { + log.info("Step 2: Migrate the relative periods into the new column 'relativeperiods'."); + // For each parent table, populate the new "relativeperiods" column with the current relative + // periods set in the "relativeperiods" table. + for (Entry selectUpdatePair : SELECT_UPDATE_PAIRS.entrySet()) { + Map idsMap = new HashMap<>(); + String parentTableSelect = selectUpdatePair.getKey(); + try (Statement statement = context.getConnection().createStatement(); + ResultSet rs = statement.executeQuery(parentTableSelect)) { + // Get the parent table column id + the relativeperiodsid. + while (rs.next()) { + idsMap.put(rs.getLong(1), rs.getLong(2)); + } + String parentTableUpdate = selectUpdatePair.getValue(); + try (PreparedStatement ps = context.getConnection().prepareStatement(parentTableUpdate)) { + // For each entry of the map, copy the relative periods to the new column + // 'relativeperiods', in the parent table. + copyPeriodsToJsonColumn(context, idsMap, ps); + } catch (SQLException e) { + log.error("Step 2 failed: ", e); + throw e; + } + } + } + } + + private static void copyPeriodsToJsonColumn( + Context context, Map idsMap, PreparedStatement ps) throws SQLException { + List periodList = new ArrayList<>(); + for (Entry ids : idsMap.entrySet()) { + Long relativePeriodsId = ids.getValue(); + Long parentTableId = ids.getKey(); + try (Statement st = context.getConnection().createStatement(); + ResultSet r = + st.executeQuery( + "select * from relativeperiods r where relativeperiodsid = " + + relativePeriodsId)) { + // Get the parent table column id + the relativeperiodsid. + while (r.next()) { + // Add the periods that are set to "true" into the list. + for (String column : PERIODS.keySet()) { + if (r.getBoolean(column)) { + periodList.add(PERIODS.get(column)); + } + } + } + } catch (SQLException e) { + log.error("Step 2 failed reading relative periods: ", e); + throw e; + } + PGobject jsonObject = new PGobject(); + jsonObject.setType("json"); + jsonObject.setValue( + periodList.stream().map((String e) -> "\"" + e + "\"").collect(toList()).toString()); + ps.setObject(1, jsonObject); + ps.setLong(2, parentTableId); + ps.executeUpdate(); + // Clear the list of periods, so it can be reused in the next iteration. + periodList.clear(); + } + } +} diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dimension/DimensionServiceTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dimension/DimensionServiceTest.java index d0cafc653750..ecff7269ab11 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dimension/DimensionServiceTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/dimension/DimensionServiceTest.java @@ -38,8 +38,13 @@ import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_LEVEL; import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT; import static org.hisp.dhis.period.RelativePeriodEnum.LAST_12_MONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_3_DAYS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_5_YEARS; +import static org.hisp.dhis.period.RelativePeriodEnum.LAST_6_MONTHS; +import static org.hisp.dhis.period.RelativePeriodEnum.THIS_WEEK; import static org.hisp.dhis.utils.Assertions.assertMapEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -478,6 +483,7 @@ void testMergeAnalyticalEventObjectB() { eventVisualization.getDataElementDimensions().get(0); assertEquals(deC, teDeDim.getDataElement()); assertEquals(psA, teDeDim.getProgramStage()); + assertTrue(eventVisualization.getRawRelativePeriods().isEmpty()); } @Test @@ -631,6 +637,7 @@ void testMergeAnalyticalObjectRelativePeriods() { assertEquals(0, visualization.getPeriods().size()); assertTrue(visualization.getRelatives().isLast12Months()); assertEquals(5, visualization.getOrganisationUnits().size()); + assertEquals(LAST_12_MONTHS.name(), visualization.getRawRelativePeriods().get(0)); } @Test @@ -665,6 +672,7 @@ void testMergeAnalyticalEventObjectRelativePeriods() { assertEquals(0, eventVisualization.getPeriods().size()); assertTrue(eventVisualization.getRelatives().isLast12Months()); assertEquals(5, eventVisualization.getOrganisationUnits().size()); + assertEquals(LAST_12_MONTHS.name(), eventVisualization.getRawRelativePeriods().get(0)); } @Test @@ -744,6 +752,51 @@ void testMergeAnalyticalObjectDataElementGroupSet() { assertEquals(2, visualization.getPeriods().size()); assertEquals(1, visualization.getDataElementGroupSetDimensions().size()); assertEquals(3, visualization.getDataElementGroupSetDimensions().get(0).getItems().size()); + assertTrue(visualization.getRawRelativePeriods().isEmpty()); + } + + @Test + void testMergeAnalyticalEventObjectWithMultiRelativePeriods() { + // Given + DimensionalItemObject peLast6Months = new BaseDimensionalItemObject(LAST_6_MONTHS.toString()); + DimensionalItemObject peLast3days = new BaseDimensionalItemObject(LAST_3_DAYS.toString()); + DimensionalItemObject peLast5Years = new BaseDimensionalItemObject(LAST_5_YEARS.toString()); + DimensionalItemObject peThisWeek = new BaseDimensionalItemObject(THIS_WEEK.toString()); + EventVisualization eventVisualization = new EventVisualization("any"); + eventVisualization + .getColumns() + .add( + new BaseDimensionalObject( + DimensionalObject.DATA_X_DIM_ID, DimensionType.DATA_X, Lists.newArrayList(deA))); + eventVisualization + .getRows() + .add( + new BaseDimensionalObject( + DimensionalObject.ORGUNIT_DIM_ID, + DimensionType.ORGANISATION_UNIT, + Lists.newArrayList(ouA))); + eventVisualization + .getFilters() + .add( + new BaseDimensionalObject( + DimensionalObject.PERIOD_DIM_ID, + DimensionType.PERIOD, + Lists.newArrayList(peLast6Months, peLast5Years, peLast3days, peThisWeek))); + // When + dimensionService.mergeAnalyticalObject(eventVisualization); + // Then + assertEquals(1, eventVisualization.getDataDimensionItems().size()); + assertEquals(1, eventVisualization.getOrganisationUnits().size()); + assertEquals(0, eventVisualization.getPeriods().size()); + assertFalse(eventVisualization.getRelatives().isLast12Months()); + assertTrue(eventVisualization.getRelatives().isLast6Months()); + assertTrue(eventVisualization.getRelatives().isLast5Years()); + assertTrue(eventVisualization.getRelatives().isLast3Days()); + assertTrue(eventVisualization.getRelatives().isThisWeek()); + assertEquals(LAST_6_MONTHS.name(), eventVisualization.getRawRelativePeriods().get(0)); + assertEquals(LAST_5_YEARS.name(), eventVisualization.getRawRelativePeriods().get(1)); + assertEquals(LAST_3_DAYS.name(), eventVisualization.getRawRelativePeriods().get(2)); + assertEquals(THIS_WEEK.name(), eventVisualization.getRawRelativePeriods().get(3)); } @Test