Skip to content

Commit

Permalink
fix: Map completed data in preheat for enrollment [DHIS2-18225] (#18850)
Browse files Browse the repository at this point in the history
* fix: Map completed data in preheat for enrollment [DHIS2-18225]

* Clean up tests
  • Loading branch information
enricocolasante authored Oct 17, 2024
1 parent 0735224 commit 40689f3
Show file tree
Hide file tree
Showing 4 changed files with 418 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public interface EnrollmentMapper extends PreheatMapper<Enrollment> {
@Mapping(target = "uid")
@Mapping(target = "code")
@Mapping(target = "user")
@Mapping(target = "completedBy")
@Mapping(target = "completedDate")
@Mapping(target = "program", qualifiedByName = "program")
@Mapping(target = "trackedEntity")
@Mapping(target = "organisationUnit")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* 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.imports.bundle;

import static org.hisp.dhis.program.EnrollmentStatus.*;
import static org.hisp.dhis.program.EnrollmentStatus.ACTIVE;
import static org.hisp.dhis.tracker.Assertions.assertNoErrors;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.io.IOException;
import java.util.stream.Stream;
import org.hisp.dhis.feedback.ForbiddenException;
import org.hisp.dhis.feedback.NotFoundException;
import org.hisp.dhis.program.Enrollment;
import org.hisp.dhis.program.EnrollmentStatus;
import org.hisp.dhis.tracker.TrackerTest;
import org.hisp.dhis.tracker.export.enrollment.EnrollmentService;
import org.hisp.dhis.tracker.imports.TrackerImportParams;
import org.hisp.dhis.tracker.imports.TrackerImportService;
import org.hisp.dhis.tracker.imports.domain.TrackerObjects;
import org.hisp.dhis.tracker.imports.report.ImportReport;
import org.hisp.dhis.user.User;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;

class EnrollmentImportTest extends TrackerTest {
@Autowired private TrackerImportService trackerImportService;

@Autowired private EnrollmentService enrollmentService;

private User importUser;

@BeforeAll
void setUp() throws IOException {
setUpMetadata("tracker/simple_metadata.json");

importUser = userService.getUser("tTgjgobT1oS");
injectSecurityContextUser(importUser);
}

@ParameterizedTest
@MethodSource("statuses")
void shouldCorrectlyPopulateCompletedDataWhenCreatingAnEnrollment(EnrollmentStatus status)
throws IOException, ForbiddenException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEnrollments().get(0).setStatus(status);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

Enrollment enrollment =
enrollmentService.getEnrollment(trackerObjects.getEnrollments().get(0).getUid());

assertEnrollmentCompletedData(enrollment);
}

@ParameterizedTest
@MethodSource("transitionStatuses")
void shouldCorrectlyPopulateCompletedDataWhenUpdatingAnEnrollment(
EnrollmentStatus savedStatus, EnrollmentStatus updatedStatus)
throws IOException, ForbiddenException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEnrollments().get(0).setStatus(savedStatus);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

trackerObjects.getEnrollments().get(0).setStatus(updatedStatus);
importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

Enrollment enrollment =
enrollmentService.getEnrollment(trackerObjects.getEnrollments().get(0).getUid());

assertEnrollmentCompletedData(enrollment);
}

public Stream<Arguments> statuses() {
return Stream.of(Arguments.of(ACTIVE), Arguments.of(CANCELLED), Arguments.of(COMPLETED));
}

public Stream<Arguments> transitionStatuses() {
return Stream.of(
Arguments.of(ACTIVE, COMPLETED),
Arguments.of(ACTIVE, CANCELLED),
Arguments.of(ACTIVE, COMPLETED),
Arguments.of(CANCELLED, COMPLETED),
Arguments.of(CANCELLED, CANCELLED),
Arguments.of(CANCELLED, COMPLETED),
Arguments.of(COMPLETED, COMPLETED),
Arguments.of(COMPLETED, CANCELLED),
Arguments.of(COMPLETED, COMPLETED));
}

private void assertEnrollmentCompletedData(Enrollment enrollment) {
switch (enrollment.getStatus()) {
case ACTIVE ->
assertAll(
() -> assertNull(enrollment.getCompletedBy()),
() -> assertNull(enrollment.getCompletedDate()));
case COMPLETED ->
assertAll(
() -> assertEquals(importUser.getUsername(), enrollment.getCompletedBy()),
() -> assertNotNull(enrollment.getCompletedDate()));
case CANCELLED ->
assertAll(
() -> assertNull(enrollment.getCompletedBy()),
() -> assertNotNull(enrollment.getCompletedDate()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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.imports.bundle;

import static org.hisp.dhis.tracker.Assertions.assertNoErrors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.io.IOException;
import java.util.stream.Stream;
import org.hisp.dhis.common.UID;
import org.hisp.dhis.event.EventStatus;
import org.hisp.dhis.feedback.ForbiddenException;
import org.hisp.dhis.feedback.NotFoundException;
import org.hisp.dhis.program.Event;
import org.hisp.dhis.tracker.TrackerTest;
import org.hisp.dhis.tracker.export.event.EventService;
import org.hisp.dhis.tracker.imports.TrackerImportParams;
import org.hisp.dhis.tracker.imports.TrackerImportService;
import org.hisp.dhis.tracker.imports.domain.TrackerObjects;
import org.hisp.dhis.tracker.imports.report.ImportReport;
import org.hisp.dhis.user.User;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;

class EventImportTest extends TrackerTest {
@Autowired private TrackerImportService trackerImportService;

@Autowired private EventService eventService;

private User importUser;

@BeforeAll
void setUp() throws IOException {
setUpMetadata("tracker/simple_metadata.json");

importUser = userService.getUser("tTgjgobT1oS");
injectSecurityContextUser(importUser);
}

@Test
void shouldPopulateCompletedDataWhenCreatingAnEventWithStatusCompleted()
throws IOException, ForbiddenException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEvents().get(0).setStatus(EventStatus.COMPLETED);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

Event event = eventService.getEvent(UID.of(trackerObjects.getEvents().get(0).getUid()));

assertEquals(importUser.getUsername(), event.getCompletedBy());
assertNotNull(event.getCompletedDate());
}

@ParameterizedTest
@MethodSource("notCompletedStatus")
void shouldNotPopulateCompletedDataWhenCreatingAnEventWithNotCompletedStatus(EventStatus status)
throws IOException, ForbiddenException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEvents().get(0).setStatus(status);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

Event event = eventService.getEvent(UID.of(trackerObjects.getEvents().get(0).getUid()));

assertNull(event.getCompletedBy());
assertNull(event.getCompletedDate());
}

@Test
void shouldDeleteCompletedDataWhenUpdatingAnEventWithStatusActive()
throws IOException, ForbiddenException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEvents().get(0).setStatus(EventStatus.COMPLETED);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

trackerObjects.getEvents().get(0).setStatus(EventStatus.ACTIVE);

importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

Event event = eventService.getEvent(UID.of(trackerObjects.getEvents().get(0).getUid()));

assertNull(event.getCompletedBy());
assertNull(event.getCompletedDate());
}

@ParameterizedTest
@MethodSource("notCompletedStatus")
void shouldPopulateCompletedDataWhenUpdatingAnEventWithStatusCompleted(EventStatus status)
throws IOException, ForbiddenException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEvents().get(0).setStatus(status);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

trackerObjects.getEvents().get(0).setStatus(EventStatus.COMPLETED);

importReport = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(importReport);

Event event = eventService.getEvent(UID.of(trackerObjects.getEvents().get(0).getUid()));

assertEquals(importUser.getUsername(), event.getCompletedBy());
assertNotNull(event.getCompletedDate());
}

public Stream<Arguments> notCompletedStatus() {
return Stream.of(
Arguments.of(EventStatus.ACTIVE),
Arguments.of(EventStatus.SCHEDULE),
Arguments.of(EventStatus.OVERDUE),
Arguments.of(EventStatus.SKIPPED));
}
}
Loading

0 comments on commit 40689f3

Please sign in to comment.