Skip to content

Commit

Permalink
AP-63 | Fix recurring appointment scenarios for Appointment Request (B…
Browse files Browse the repository at this point in the history
…ahmni#37)

* Update/Cancel all for appointment with Requested Status

* Add AWAITING response as filter condition for deep copying providers in case of recurring appointments
  • Loading branch information
mddubey authored Jun 22, 2020
1 parent 2eaef1c commit 21882b2
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -112,7 +111,7 @@ public List<Appointment> changeStatus(Appointment appointment, String status, St
String serverTimeZone = Calendar.getInstance().getTimeZone().getID();
TimeZone.setDefault(TimeZone.getTimeZone(clientTimeZone));
List<Appointment> pendingAppointments = getPendingOccurrences(appointment.getUuid(),
Arrays.asList(AppointmentStatus.Scheduled, AppointmentStatus.CheckedIn));
Arrays.asList(AppointmentStatus.Requested, AppointmentStatus.Scheduled, AppointmentStatus.CheckedIn));
TimeZone.setDefault(TimeZone.getTimeZone(serverTimeZone));
pendingAppointments.stream()
.map(pendingAppointment -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ private boolean validateIfUserHasSelfOrAllAppointmentsAccess(Appointment appoint
}

private boolean isAppointmentNotAssignedToAnyProvider(Appointment appointment) {
return appointment.getProvidersWithResponse(AppointmentProviderResponse.ACCEPTED).isEmpty();
return appointment.getProvidersWithResponse(AppointmentProviderResponse.ACCEPTED).isEmpty()
&& appointment.getProvidersWithResponse(AppointmentProviderResponse.AWAITING).isEmpty();
}

private boolean isCurrentUserSamePersonAsOneOfTheAppointmentProviders(Set<AppointmentProvider> providers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
import static org.openmrs.module.appointments.model.AppointmentStatus.CheckedIn;
import static org.openmrs.module.appointments.model.AppointmentStatus.Requested;
import static org.openmrs.module.appointments.model.AppointmentStatus.Scheduled;

@RunWith(MockitoJUnitRunner.class)
Expand Down Expand Up @@ -149,6 +150,60 @@ public void shouldUpdateStatusOfScheduledFutureOccurrences() {
verify(appointmentDao, times(2)).save(any(Appointment.class));
}

@Test
public void shouldUpdateStatusOfRequestedFutureOccurrences() {
Calendar startTimeCalendar = Calendar.getInstance();
Calendar endTimeCalendar = Calendar.getInstance();
Calendar newStartTimeCalendar = Calendar.getInstance();
Calendar newEndTimeCalendar = Calendar.getInstance();
int year = startTimeCalendar.get(Calendar.YEAR);
int month = startTimeCalendar.get(Calendar.MONTH);
int day = startTimeCalendar.get(Calendar.DATE);
startTimeCalendar.set(year, month, day, 10, 00, 00);
endTimeCalendar.set(year, month, day, 10, 30, 00);
newStartTimeCalendar.set(year, month, day, 12, 00, 00);
newStartTimeCalendar.set(Calendar.MILLISECOND, 0);
newEndTimeCalendar.set(year, month, day, 12, 30, 00);
newEndTimeCalendar.set(Calendar.MILLISECOND, 0);
AppointmentRecurringPattern appointmentRecurringPattern = new AppointmentRecurringPattern();
appointmentRecurringPattern.setType(RecurringAppointmentType.DAY);
appointmentRecurringPattern.setFrequency(3);
appointmentRecurringPattern.setPeriod(2);
Appointment appointmentOne = getAppointment("uuid1", patient,
Requested,
AppointmentKind.Scheduled,
DateUtils.addDays(startTimeCalendar.getTime(), -2),
DateUtils.addDays(endTimeCalendar.getTime(), -2));
Appointment appointmentTwo = getAppointment("uuid2", patient,
CheckedIn,
AppointmentKind.Scheduled,
startTimeCalendar.getTime(),
endTimeCalendar.getTime());
appointmentTwo.setAppointmentAudits(new HashSet<>());
Appointment appointmentThree = getAppointment("uuid3", patient,
Requested,
AppointmentKind.Scheduled,
DateUtils.addDays(startTimeCalendar.getTime(), 2),
DateUtils.addDays(endTimeCalendar.getTime(), 2));
appointmentThree.setAppointmentAudits(new HashSet<>());
Set<Appointment> appointments = new HashSet<>(Arrays.asList(appointmentOne, appointmentTwo, appointmentThree));
appointmentRecurringPattern.setAppointments(appointments);
appointmentOne.setAppointmentRecurringPattern(appointmentRecurringPattern);
appointmentTwo.setAppointmentRecurringPattern(appointmentRecurringPattern);
appointmentThree.setAppointmentRecurringPattern(appointmentRecurringPattern);
when(appointmentDao.getAppointmentByUuid(anyString())).thenReturn(appointmentTwo);
doNothing().when(appointmentServiceHelper).validate(appointmentTwo, editAppointmentValidators);

AppointmentAudit appointmentAudit = new AppointmentAudit();
appointmentAudit.setNotes(null);
appointmentAudit.setAppointment(appointmentTwo);
appointmentAudit.setStatus(CheckedIn);
when(appointmentServiceHelper.getAppointmentAuditEvent(appointmentTwo, null)).thenReturn(appointmentAudit);

recurringAppointmentService.changeStatus(appointmentTwo, "Cancelled", "");
verify(appointmentDao, times(2)).save(any(Appointment.class));
}

@Test
public void shouldUpdateStatusOfScheduledCurrentAndFutureOccurrences() throws IOException {
Calendar startTimeCalendar = Calendar.getInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Component
Expand Down Expand Up @@ -92,7 +93,7 @@ private void updateMetadataForAllAppointments(Appointment appointment, String cl
.setAppointments(appointment.getAppointmentRecurringPattern().getAppointments()
.stream()
.map(app -> {
if (app.isFutureAppointment() && app.getStatus() == AppointmentStatus.Scheduled) {
if (app.isFutureAppointment() && isRequestedOrScheduledAppointment(app)) {
TimeZone.setDefault(TimeZone.getTimeZone(clientTimeZone));
updateMetadata(app, appointment);
TimeZone.setDefault(TimeZone.getTimeZone(serverTimeZone));
Expand All @@ -101,6 +102,10 @@ private void updateMetadataForAllAppointments(Appointment appointment, String cl
}).collect(Collectors.toSet()));
}

private boolean isRequestedOrScheduledAppointment(Appointment app) {
return app.getStatus() == AppointmentStatus.Requested || app.getStatus() == AppointmentStatus.Scheduled;
}

private void updateMetadata(Appointment pendingAppointment, Appointment appointment) {
Date startTime = getStartTime(pendingAppointment, appointment);
Date endTime = getEndTime(pendingAppointment, appointment);
Expand Down Expand Up @@ -144,11 +149,16 @@ private List<AppointmentProvider> getDeepCloneOfProviders(Set<AppointmentProvide
return new ArrayList<>();
return appointmentProviders
.stream()
.filter(provider -> AppointmentProviderResponse.ACCEPTED.equals(provider.getResponse()))
.filter(isAcceptedOrAwaitingProvider())
.map(AppointmentProvider::new)
.collect(Collectors.toList());
}

private Predicate<AppointmentProvider> isAcceptedOrAwaitingProvider() {
return provider -> AppointmentProviderResponse.ACCEPTED.equals(provider.getResponse())
|| AppointmentProviderResponse.AWAITING.equals(provider.getResponse());
}

private void mapProvidersForAppointment(Appointment appointment, List<AppointmentProvider> newProviders) {
Set<AppointmentProvider> existingProviders = appointment.getProviders();
setRemovedProvidersToCancel(newProviders, existingProviders);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void should_GetAllAppointments() throws Exception {
= deserialize(handle(newGetRequest("/rest/v1/appointment/all")),
new TypeReference<List<AppointmentDefaultResponse>>() {
});
assertEquals(13, asResponses.size());
assertEquals(17, asResponses.size());
}

@Test
Expand Down Expand Up @@ -97,7 +97,7 @@ public void shouldGetAllNonVoidedNonCancelledFutureAppointmentsforaServiceType()
List<AppointmentDefaultResponse> asResponse = deserialize(handle(getRequest),
new TypeReference<List<AppointmentDefaultResponse>>() {});

assertEquals(9, asResponse.size());
assertEquals(13, asResponse.size());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,37 @@ public void shouldUpdateRecurringAppointmentWhenApplyForAllIsTrue() throws Excep
assertEquals(200, response.getStatus());
}

@Test
public void shouldUpdateRecurringAppointmentForRequestedStatusWhenApplyForAllIsTrue() throws Exception {
String content = "{ \"appointmentRequest\":{" +
"\"uuid\": \"25a7e84b-6933-49cc-aebe-c1d4d33a86y2\", " +
"\"appointmentNumber\": \"1\", " +
"\"patientUuid\": \"2c33920f-7aa6-48d6-998a-60412d8ff7d5\", " +
"\"serviceUuid\": \"c36006d4-9fbb-4f20-866b-0ece245615c1\", " +
"\"serviceTypeUuid\": \"672546e5-9fbb-4f20-866b-0ece24564578\", " +
"\"startDateTime\": \"2017-07-20\", " +
"\"endDateTime\": \"2017-07-20\", " +
"\"comments\": \"Some notes\", " +
"\"appointmentKind\": \"WalkIn\"," +
"\"providers\": [{\"uuid\":\"2bdc3f7d-d911-401a-84e9-5494dda83e8e\"}]}," +
"\"applyForAll\": true," +
"\"timeZone\": \"IST\"," +
"\"recurringPattern\":{" +
"\"frequency\":2," +
"\"period\":1," +
"\"daysOfWeek\":[]," +
"\"type\":\"Day\"" +
"}}";
MockHttpServletResponse response = handle(newPutRequest("/rest/v1/recurring-appointments/uuid", content));
assertNotNull(response);
assertEquals(200, response.getStatus());
List<RecurringAppointmentDefaultResponse> appointmentDefaultResponse = deserialize(response, new TypeReference<List<RecurringAppointmentDefaultResponse>>() {
});
for (RecurringAppointmentDefaultResponse recurringAppointmentDefaultResponse : appointmentDefaultResponse) {
assertEquals(1, recurringAppointmentDefaultResponse.getAppointmentDefaultResponse().getProviders().size());
}
}

@Test
public void shouldUpdateRecurringAppointmentByAddingAppointmentsWhenFrequencyIsChanged() throws Exception {
String content = "{ \"appointmentRequest\":{" +
Expand Down Expand Up @@ -555,4 +586,30 @@ public void shouldReturnNineAppointmentsOnUpdateFromSix() throws Exception {
assertEquals(9, appointmentDefaultResponse.size());

}

@Test
public void shouldUpdateRecurringAppointmentForRequestedAppointmentWhenApplyForAllIsTrue() throws Exception {
String content = "{ \"appointmentRequest\":{" +
"\"uuid\": \"c36006e5-9fbb-4f20-866b-0ece245615a7\", " +
"\"appointmentNumber\": \"1\", " +
"\"patientUuid\": \"2c33920f-7aa6-48d6-998a-60412d8ff7d5\", " +
"\"serviceUuid\": \"c36006d4-9fbb-4f20-866b-0ece245615c1\", " +
"\"serviceTypeUuid\": \"672546e5-9fbb-4f20-866b-0ece24564578\", " +
"\"startDateTime\": \"2017-07-20\", " +
"\"endDateTime\": \"2017-07-20\", " +
"\"comments\": \"Some notes\", " +
"\"appointmentKind\": \"WalkIn\"," +
"\"providers\": []}," +
"\"applyForAll\": true," +
"\"timeZone\": \"UTC\"," +
"\"recurringPattern\":{" +
"\"frequency\":2," +
"\"period\":1," +
"\"daysOfWeek\":[]," +
"\"type\":\"Day\"" +
"}}";
MockHttpServletResponse response = handle(newPutRequest("/rest/v1/recurring-appointments/uuid", content));
assertNotNull(response);
assertEquals(200, response.getStatus());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import static org.openmrs.module.appointments.model.AppointmentProviderResponse.CANCELLED;
import static org.openmrs.module.appointments.model.AppointmentStatus.CheckedIn;
import static org.openmrs.module.appointments.model.AppointmentStatus.Completed;
import static org.openmrs.module.appointments.model.AppointmentStatus.Requested;
import static org.openmrs.module.appointments.model.AppointmentStatus.Scheduled;

@RunWith(PowerMockRunner.class)
Expand Down Expand Up @@ -354,6 +355,76 @@ AppointmentKind.Scheduled, new AppointmentServiceDefinition(), new AppointmentSe
verify(appointmentMapper).mapAppointmentRequestToAppointment(recurringAppointmentRequest.getAppointmentRequest(), appointmentTwo);
}

@Test
public void shouldUpdateNewAwaitingProviderForAllPendingOccurrences() throws IOException {
RecurringAppointmentRequest recurringAppointmentRequest = new RecurringAppointmentRequest();
recurringAppointmentRequest.setAppointmentRequest(new AppointmentRequest());
RecurringPattern recurringPattern = new RecurringPattern();
recurringPattern.setFrequency(3);
recurringPattern.setEndDate(null);
recurringAppointmentRequest.setRecurringPattern(recurringPattern);
recurringAppointmentRequest.getAppointmentRequest().setUuid("uuid2");
recurringAppointmentRequest.setTimeZone("Asia/Calcutta");
Calendar startTimeCalendar = Calendar.getInstance();
Calendar endTimeCalendar = Calendar.getInstance();
int year = startTimeCalendar.get(Calendar.YEAR);
int month = startTimeCalendar.get(Calendar.MONTH);
int day = startTimeCalendar.get(Calendar.DATE);
startTimeCalendar.set(year, month, day, 18, 00, 00);
endTimeCalendar.set(year, month, day, 18, 30, 00);
AppointmentRecurringPattern appointmentRecurringPattern = new AppointmentRecurringPattern();
appointmentRecurringPattern.setType(RecurringAppointmentType.DAY);
appointmentRecurringPattern.setFrequency(3);
appointmentRecurringPattern.setPeriod(2);
AppointmentProvider appointmentProvider = new AppointmentProvider();
appointmentProvider.setProvider(new Provider(101));
appointmentProvider.setResponse(AppointmentProviderResponse.AWAITING);
HashSet<AppointmentProvider> appointmentProviders = new HashSet<>(Collections.singleton(appointmentProvider));

AppointmentProvider appointmentProviderTwo = new AppointmentProvider();
appointmentProviderTwo.setProvider(new Provider(102));
appointmentProviderTwo.setResponse(AppointmentProviderResponse.AWAITING);
HashSet<AppointmentProvider> appointmentProvidersTwo = new HashSet<>(Arrays.asList(appointmentProvider, appointmentProviderTwo));

Appointment appointmentOne = createAppointment("uuid1", patient, Requested,
AppointmentKind.Scheduled, new AppointmentServiceDefinition(), new AppointmentServiceType(),
new Location(), appointmentProviders, "appOne",
DateUtils.addDays(startTimeCalendar.getTime(), 2),
DateUtils.addDays(endTimeCalendar.getTime(), 2));
Appointment appointmentTwo = createAppointment("uuid2", patient, Requested,
AppointmentKind.Scheduled, new AppointmentServiceDefinition(), new AppointmentServiceType(),
new Location(), appointmentProvidersTwo, "appTwo", startTimeCalendar.getTime(),
endTimeCalendar.getTime());
Appointment appointmentThree = createAppointment("uuid3", patient, Requested,
AppointmentKind.Scheduled, new AppointmentServiceDefinition(), new AppointmentServiceType(),
new Location(), appointmentProviders, "appThree",
DateUtils.addDays(startTimeCalendar.getTime(), 2),
DateUtils.addDays(endTimeCalendar.getTime(), 2));

appointmentThree.setAppointmentAudits(new HashSet<>());
Set<Appointment> appointments = new HashSet<>(Arrays.asList(appointmentOne, appointmentTwo, appointmentThree));
appointmentRecurringPattern.setAppointments(appointments);
appointmentOne.setAppointmentRecurringPattern(appointmentRecurringPattern);
appointmentTwo.setAppointmentRecurringPattern(appointmentRecurringPattern);
appointmentThree.setAppointmentRecurringPattern(appointmentRecurringPattern);


when(appointmentsService.getAppointmentByUuid(any())).thenReturn(appointmentTwo);
when(recurringAppointmentsService.getUpdatedSetOfAppointments(appointmentRecurringPattern, recurringAppointmentRequest))
.thenReturn(new ArrayList<>(appointments));

AppointmentRecurringPattern updatedRecurringPattern = allAppointmentRecurringPatternUpdateService
.getUpdatedRecurringPattern(recurringAppointmentRequest);

assertEquals(3, updatedRecurringPattern.getAppointments().size());
updatedRecurringPattern.getAppointments().forEach(a -> {
assertEquals(2, a.getProviders().size());
});
verify(appointmentsService, times(1)).getAppointmentByUuid(anyString());
verify(recurringAppointmentsService).getUpdatedSetOfAppointments(appointmentRecurringPattern, recurringAppointmentRequest);
verify(appointmentMapper).mapAppointmentRequestToAppointment(recurringAppointmentRequest.getAppointmentRequest(), appointmentTwo);
}

@Test
public void shouldSetAllProvidersToCancelWhenAllProvidersRemoved() throws IOException {
RecurringAppointmentRequest recurringAppointmentRequest = new RecurringAppointmentRequest();
Expand Down
Loading

0 comments on commit 21882b2

Please sign in to comment.