diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EnrollmentTrackerConverterService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EnrollmentTrackerConverterService.java index 32354a90ddfa..b7a198c7b18e 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EnrollmentTrackerConverterService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EnrollmentTrackerConverterService.java @@ -107,7 +107,12 @@ public Enrollment fromForRuleEngine( TrackerPreheat preheat, org.hisp.dhis.tracker.imports.domain.Enrollment enrollment, UserDetails user) { - return from(preheat, enrollment, null, user); + Enrollment from = from(preheat, enrollment, null, user); + Enrollment preheatEnrollment = preheat.getEnrollment(enrollment.getUid()); + if (preheatEnrollment != null) { + from.setCreated(preheatEnrollment.getCreated()); + } + return from; } private Enrollment from( diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EventTrackerConverterService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EventTrackerConverterService.java index 16ea2a81d62c..2a70de125ac3 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EventTrackerConverterService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/converter/EventTrackerConverterService.java @@ -165,6 +165,10 @@ public Event fromForRuleEngine( Event result = from(preheat, event, null, user); // merge data values from DB result.getEventDataValues().addAll(getDataValues(preheat, event)); + Event preheatEvent = preheat.getEvent(event.getUid()); + if (preheatEvent != null) { + result.setCreated(preheatEvent.getCreated()); + } return result; } @@ -209,8 +213,8 @@ private Event from( result.setCreated(now); result.setStoredBy(event.getStoredBy()); result.setCreatedByUserInfo(UserInfoSnapshot.from(user)); - result.setCreatedAtClient(DateUtils.fromInstant(event.getCreatedAtClient())); } + result.setCreatedAtClient(DateUtils.fromInstant(event.getCreatedAtClient())); result.setLastUpdatedByUserInfo(UserInfoSnapshot.from(user)); result.setLastUpdated(now); result.setDeleted(false); diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/programrule/engine/DefaultProgramRuleEntityMapperService.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/programrule/engine/DefaultProgramRuleEntityMapperService.java index 488528c70f51..93abbec70f7f 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/programrule/engine/DefaultProgramRuleEntityMapperService.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/programrule/engine/DefaultProgramRuleEntityMapperService.java @@ -222,6 +222,7 @@ public RuleEvent toMappedRuleEvent(@Nonnull Event eventToEvaluate) { eventToEvaluate.getOccurredDate() != null ? Instant.Companion.fromEpochMilliseconds(eventToEvaluate.getOccurredDate().getTime()) : Instant.Companion.fromEpochMilliseconds(eventToEvaluate.getScheduledDate().getTime()), + Instant.Companion.fromEpochMilliseconds(eventToEvaluate.getCreated().getTime()), eventToEvaluate.getScheduledDate() == null ? null : LocalDateTime.Formats.INSTANCE @@ -239,17 +240,7 @@ public RuleEvent toMappedRuleEvent(@Nonnull Event eventToEvaluate) { eventToEvaluate.getEventDataValues().stream() .filter(Objects::nonNull) .filter(dv -> dv.getValue() != null) - .map( - dv -> - new RuleDataValue( - eventToEvaluate.getOccurredDate() != null - ? Instant.Companion.fromEpochMilliseconds( - eventToEvaluate.getOccurredDate().getTime()) - : Instant.Companion.fromEpochMilliseconds( - eventToEvaluate.getScheduledDate().getTime()), - eventToEvaluate.getProgramStage().getUid(), - dv.getDataElement(), - dv.getValue())) + .map(dv -> new RuleDataValue(dv.getDataElement(), dv.getValue())) .toList()); } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/programrule/engine/ProgramRuleEntityMapperServiceTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/programrule/engine/ProgramRuleEntityMapperServiceTest.java index 90fee82d7c3f..8c1ade770809 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/programrule/engine/ProgramRuleEntityMapperServiceTest.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/programrule/engine/ProgramRuleEntityMapperServiceTest.java @@ -558,6 +558,7 @@ private void assertEvent(Event event, RuleEvent ruleEvent) { assertEquals(event.getStatus().name(), ruleEvent.getStatus().name()); assertDates(event.getOccurredDate(), ruleEvent.getEventDate()); assertNull(ruleEvent.getCompletedDate()); + assertDates(event.getCreated(), ruleEvent.getCreatedDate()); assertEquals(event.getOrganisationUnit().getUid(), ruleEvent.getOrganisationUnit()); assertEquals(event.getOrganisationUnit().getCode(), ruleEvent.getOrganisationUnitCode()); assertDataValue(event.getEventDataValues().iterator().next(), ruleEvent.getDataValues().get(0)); diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/programrule/ProgramRuleAssignActionTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/programrule/ProgramRuleAssignActionTest.java index 4fc65a34a942..e1e24a3db31a 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/programrule/ProgramRuleAssignActionTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/imports/programrule/ProgramRuleAssignActionTest.java @@ -29,6 +29,7 @@ import static org.hisp.dhis.programrule.ProgramRuleActionType.ASSIGN; import static org.hisp.dhis.test.utils.Assertions.assertContainsOnly; +import static org.hisp.dhis.test.utils.Assertions.assertIsEmpty; import static org.hisp.dhis.tracker.Assertions.assertHasOnlyErrors; import static org.hisp.dhis.tracker.Assertions.assertHasOnlyWarnings; import static org.hisp.dhis.tracker.imports.validation.ValidationCode.E1307; @@ -37,6 +38,7 @@ import java.io.IOException; import java.util.List; +import org.hisp.dhis.common.CodeGenerator; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundle; import org.hisp.dhis.eventdatavalue.EventDataValue; @@ -63,6 +65,7 @@ import org.hisp.dhis.tracker.imports.report.ImportReport; import org.hisp.dhis.user.User; import org.hisp.dhis.util.DateUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -167,6 +170,57 @@ void shouldImportEventAndCorrectlyAssignPreviousEventDataValue( assertContainsOnly(List.of(previousEventDataValue), eventDataValues); } + @Test + void + shouldImportEventAndCorrectlyAssignPreviousEventDataValueConsideringCreateAtWhenOccurredAtIsSame() + throws IOException { + String firstEventUid = CodeGenerator.generateUid(); + String secondEventUid = CodeGenerator.generateUid(); + String thirdEventUid = CodeGenerator.generateUid(); + String fourthEventUid = CodeGenerator.generateUid(); + TrackerImportParams params = new TrackerImportParams(); + params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE); + + // Events are imported separately to have different createdAt + TrackerObjects firstEvent = getEvent(firstEventUid, "2024-01-11", "FIRST"); + trackerImportService.importTracker(params, firstEvent); + + TrackerObjects fourthEvent = getEvent(fourthEventUid, "2024-01-26", "FOURTH"); + trackerImportService.importTracker(params, fourthEvent); + + TrackerObjects secondEvent = getEvent(secondEventUid, "2024-01-25", "SECOND"); + trackerImportService.importTracker(params, secondEvent); + + TrackerObjects thirdEvent = getEvent(thirdEventUid, "2024-01-25", "THIRD"); + trackerImportService.importTracker(params, thirdEvent); + + assignPreviousEventProgramRule(); + + TrackerObjects trackerObjects = + TrackerObjects.builder() + .events( + List.of( + firstEvent.getEvents().get(0), + secondEvent.getEvents().get(0), + thirdEvent.getEvents().get(0), + fourthEvent.getEvents().get(0))) + .build(); + + ImportReport importReport = trackerImportService.importTracker(params, trackerObjects); + + List firstEventDataValues = getValueForAssignedDataElement(firstEventUid); + List secondEventDataValues = getValueForAssignedDataElement(secondEventUid); + List thirdEventDataValues = getValueForAssignedDataElement(thirdEventUid); + List fourthEventDataValues = getValueForAssignedDataElement(fourthEventUid); + + Assertions.assertAll( + () -> assertHasOnlyWarnings(importReport, E1308, E1308, E1308, E1308), + () -> assertIsEmpty(firstEventDataValues), + () -> assertContainsOnly(List.of("FIRST"), secondEventDataValues), + () -> assertContainsOnly(List.of("SECOND"), thirdEventDataValues), + () -> assertContainsOnly(List.of("THIRD"), fourthEventDataValues)); + } + @Test void shouldImportWithWarningWhenDataElementWithSameValueIsAssignedByAssignRule() throws IOException { @@ -226,6 +280,26 @@ void shouldNotImportWhenDataElementWithDifferentValueIsAssignedByAssignRule() th assertHasOnlyWarnings(importReport, E1308); } + private TrackerObjects getEvent(String eventUid, String occurredDate, String value) + throws IOException { + TrackerObjects trackerObjects = fromJson("tracker/programrule/event_without_date.json"); + trackerObjects + .getEvents() + .get(0) + .setOccurredAt(DateUtils.instantFromDateAsString(occurredDate)); + trackerObjects.getEvents().get(0).setEvent(eventUid); + trackerObjects.getEvents().get(0).getDataValues().iterator().next().setValue(value); + + return trackerObjects; + } + + private List getValueForAssignedDataElement(String eventUid) { + return manager.get(Event.class, eventUid).getEventDataValues().stream() + .filter(dv -> dv.getDataElement().equals("DATAEL00002")) + .map(EventDataValue::getValue) + .toList(); + } + private void assignProgramRule() { ProgramRule programRule = createProgramRule('F', program, null, "true"); programRuleService.addProgramRule(programRule); diff --git a/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_with_data_value.json b/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_with_data_value.json index 0a936632d9dc..3c41ce0ed0c4 100644 --- a/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_with_data_value.json +++ b/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_with_data_value.json @@ -19,8 +19,7 @@ "identifier": "h4w96yEMlzO" }, "relationships": [], - "occurredAt": "2024-02-01T00:00:00.000", - "scheduledAt": "2019-01-28T12:10:38.100", + "scheduledAt": "2019-01-25T12:10:38.100", "storedBy": "admin", "deleted": false, "attributeOptionCombo": { diff --git a/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_without_date.json b/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_without_date.json new file mode 100644 index 000000000000..72ef4ca0d72e --- /dev/null +++ b/dhis-2/dhis-test-integration/src/test/resources/tracker/programrule/event_without_date.json @@ -0,0 +1,43 @@ +{ + "trackedEntities": [], + "enrollments": [], + "events": [ + { + "status": "COMPLETED", + "program": { + "idScheme": "UID", + "identifier": "BFcipDERJnf" + }, + "programStage": { + "idScheme": "UID", + "identifier": "NpsdDv6kKSO" + }, + "enrollment": "TvctPPhpD8u", + "orgUnit": { + "idScheme": "UID", + "identifier": "h4w96yEMlzO" + }, + "relationships": [], + "scheduledAt": "2019-01-25T12:10:38.100", + "storedBy": "admin", + "deleted": false, + "attributeOptionCombo": { + "idScheme": "UID" + }, + "attributeCategoryOptions": [], + + "dataValues": [ + { + "storedBy": "admin", + "providedElsewhere": false, + "dataElement": { + "idScheme": "UID", + "identifier": "DATAEL00001" + } + } + ], + "notes": [] + } + ], + "relationships": [] +} \ No newline at end of file diff --git a/dhis-2/pom.xml b/dhis-2/pom.xml index 8553810587c2..30982504c036 100644 --- a/dhis-2/pom.xml +++ b/dhis-2/pom.xml @@ -93,7 +93,7 @@ - 3.0.1 + 3.1.0 0.6.0