Skip to content

Commit

Permalink
HTML-842: Add Appointments Tag
Browse files Browse the repository at this point in the history
  • Loading branch information
mogoodrich committed May 24, 2024
1 parent 3712bfe commit f3e379b
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ public void setupRequest(MockHttpServletRequest request, Map<String, String> wid
request.setParameter(widgets.get("Location:"), "2");
request.setParameter(widgets.get("Provider:"), "502");
request.setParameter(widgets.get("Appointments:"), "05f2ad92-1cc8-4cec-bf54-9cac0200746d");
request.setParameter(widgets.get("Appointments:").replace("_1", "_2"),
"75504r42-3ca8-11e3-bf2b-0800271c1111");
request.setParameter(widgets.get("Appointments:").replace("_05f2ad92-1cc8-4cec-bf54-9cac0200746d",
"_75504r42-3ca8-11e3-bf2b-0800271c1111"), "75504r42-3ca8-11e3-bf2b-0800271c1111");
}

@Override
Expand Down Expand Up @@ -167,8 +167,8 @@ public String[] widgetLabelsForEdit() {

public void setupEditRequest(MockHttpServletRequest request, Map<String, String> widgets) {
request.setParameter(widgets.get("Appointments:"), "");
request.setParameter(widgets.get("Appointments:").replace("_1", "_2"),
"75504r42-3ca8-11e3-bf2b-0800271c1111");
request.setParameter(widgets.get("Appointments:").replace("_05f2ad92-1cc8-4cec-bf54-9cac0200746d",
"_75504r42-3ca8-11e3-bf2b-0800271c1111"), "75504r42-3ca8-11e3-bf2b-0800271c1111");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
import org.openmrs.Relationship;
import org.openmrs.api.ObsService;
import org.openmrs.api.context.Context;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.appointments.model.AppointmentStatus;
import org.openmrs.module.appointments.service.AppointmentsService;
import org.openmrs.module.htmlformentry.FormEntryContext.Mode;
import org.openmrs.module.htmlformentry.appointment.AppointmentsAbstractor;
import org.openmrs.module.htmlformentry.property.ExitFromCareProperty;
import org.openmrs.module.htmlformentry.velocity.VelocityContextContentProvider;
import org.openmrs.module.htmlformentry.widget.AutocompleteWidget;
Expand All @@ -47,7 +45,6 @@
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -642,29 +639,13 @@ public void applyActions() throws BadFormDesignException {

// handle appointments (needs to happen after encounter is saved?)
if (submissionActions.getAppointmentsToMarkCheckedInAndAssociateWithEncounter() != null) {
for (Appointment appointment : submissionActions.getAppointmentsToMarkCheckedInAndAssociateWithEncounter()) {
if (appointment.getStatus() == AppointmentStatus.Scheduled) {
Context.getService(AppointmentsService.class).changeStatus(appointment,
AppointmentStatus.CheckedIn.toString(), encounter.getEncounterDatetime());
}
if (appointment.getFulfillingEncounters() != null) {
appointment.getFulfillingEncounters().add(encounter);
} else {
appointment.setFulfillingEncounters(Collections.singleton(encounter));
}
// see: https://bahmni.atlassian.net/browse/BAH-3855 for why we need to call the Supplier<Appointment> version of validateAndSave
Context.getService(AppointmentsService.class).validateAndSave(() -> appointment);
}
new AppointmentsAbstractor().markAppointmentsAsCheckedInAndAssociateWithEncounter(
submissionActions.getAppointmentsToMarkCheckedInAndAssociateWithEncounter(), encounter);
}

if (submissionActions.getAppointmentsToDisassociateFromEncounter() != null) {
for (Appointment appointment : submissionActions.getAppointmentsToDisassociateFromEncounter()) {
if (appointment.getFulfillingEncounters() != null) {
appointment.getFulfillingEncounters().remove(encounter);
// see: https://bahmni.atlassian.net/browse/BAH-3855 for why we need to call the Supplier<Appointment> version of validateAndSave
Context.getService(AppointmentsService.class).validateAndSave(() -> appointment);
}
}
new AppointmentsAbstractor().disassociateAppointmentsFromEncounter(
submissionActions.getAppointmentsToDisassociateFromEncounter(), encounter);
}

//deal with relationships
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ public class FormSubmissionActions {

private List<PatientIdentifier> identifiersToVoid = new Vector<PatientIdentifier>();

private List<Appointment> appointmentsToMarkCheckedInAndAssociateWithEncounter = new Vector<Appointment>();
private List<Object> appointmentsToMarkCheckedInAndAssociateWithEncounter = new Vector<Object>();

private List<Appointment> appointmentsToDisassociateFromEncounter = new Vector<Appointment>();
private List<Object> appointmentsToDisassociateFromEncounter = new Vector<Object>();

private ExitFromCareProperty exitFromCareProperty;

Expand Down Expand Up @@ -952,20 +952,20 @@ public void setCustomFormSubmissionActions(List<CustomFormSubmissionAction> cust
this.customFormSubmissionActions = customFormSubmissionActions;
}

public List<Appointment> getAppointmentsToMarkCheckedInAndAssociateWithEncounter() {
public List<Object> getAppointmentsToMarkCheckedInAndAssociateWithEncounter() {
return appointmentsToMarkCheckedInAndAssociateWithEncounter;
}

public void setAppointmentsToMarkCheckedInAndAssociateWithEncounter(
List<Appointment> appointmentsToMarkCheckedInAndAssociateWithEncounter) {
List<Object> appointmentsToMarkCheckedInAndAssociateWithEncounter) {
this.appointmentsToMarkCheckedInAndAssociateWithEncounter = appointmentsToMarkCheckedInAndAssociateWithEncounter;
}

public List<Appointment> getAppointmentsToDisassociateFromEncounter() {
public List<Object> getAppointmentsToDisassociateFromEncounter() {
return appointmentsToDisassociateFromEncounter;
}

public void setAppointmentsToDisassociateFromEncounter(List<Appointment> appointmentsToDisassociateFromEncounter) {
public void setAppointmentsToDisassociateFromEncounter(List<Object> appointmentsToDisassociateFromEncounter) {
this.appointmentsToDisassociateFromEncounter = appointmentsToDisassociateFromEncounter;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.openmrs.module.htmlformentry.appointment;

import java.util.Collections;
import java.util.List;

import org.openmrs.Encounter;
import org.openmrs.api.context.Context;
import org.openmrs.module.appointments.model.Appointment;
import org.openmrs.module.appointments.model.AppointmentStatus;
import org.openmrs.module.appointments.service.AppointmentsService;

/**
* Calls to the AppointmentService are abstracted here, rather than directly accessed in the Form
* Entry Session to avoid runtime class loading issues in instances where the Appointments module is
* not present
*/
public class AppointmentsAbstractor {

public void markAppointmentsAsCheckedInAndAssociateWithEncounter(List<Object> appointments, Encounter encounter) {
for (Object appointmentObject : appointments) {
Appointment appointment = (Appointment) appointmentObject;
if (appointment.getStatus() == AppointmentStatus.Scheduled) {
Context.getService(AppointmentsService.class).changeStatus(appointment,
AppointmentStatus.CheckedIn.toString(), encounter.getEncounterDatetime());
}
if (appointment.getFulfillingEncounters() != null) {
appointment.getFulfillingEncounters().add(encounter);
} else {
appointment.setFulfillingEncounters(Collections.singleton(encounter));
}
// see: https://bahmni.atlassian.net/browse/BAH-3855 for why we need to call the Supplier<Appointment> version of validateAndSave
Context.getService(AppointmentsService.class).validateAndSave(() -> appointment);
}
}

public void disassociateAppointmentsFromEncounter(List<Object> appointments, Encounter encounter) {
for (Object appointmentObject : appointments) {
Appointment appointment = (Appointment) appointmentObject;
if (appointment.getFulfillingEncounters() != null) {
appointment.getFulfillingEncounters().remove(encounter);
// see: https://bahmni.atlassian.net/browse/BAH-3855 for why we need to call the Supplier<Appointment> version of validateAndSave
Context.getService(AppointmentsService.class).validateAndSave(() -> appointment);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,22 @@ public AppointmentsElement(FormEntryContext context, Map<String, String> paramet
// first, get all scheduled appointments for this patient
AppointmentSearchRequest request = new AppointmentSearchRequest();
request.setPatientUuid(patient.getUuid());
request.setStartDate(new DateTime().minusYears(1000).toDate()); // hack, we want all appts for patient regardless of start date, but the search method always returns null if start date is null; this will start to fail in a thousand years
request.setStartDate(new DateTime().minusYears(1000).toDate()); // hack, see: https://bahmni.atlassian.net/browse/BAH-3867; this will start to fail in a thousand years
appointments = Context.getService(AppointmentsService.class).search(request);

appointments.sort(Comparator.comparing(Appointment::getStartDateTime).reversed());

// in VIEW mode, only show appointments linked to encounter; in EDIT mode show those linked to encounter and all scheduled appts
appointments.removeIf(appointment -> (context.getMode() == FormEntryContext.Mode.VIEW
|| appointment.getStatus() != AppointmentStatus.Scheduled)
&& (appointment.getFulfillingEncounters() == null
|| !appointment.getFulfillingEncounters().contains(context.getExistingEncounter())));
// in VIEW mode, only show appointments linked to encounter;
if (context.getMode() == FormEntryContext.Mode.VIEW) {
appointments.removeIf(appointment -> appointment.getFulfillingEncounters() == null
|| !appointment.getFulfillingEncounters().contains(context.getExistingEncounter()));
}
// in ENTER and EDIT mode show those linked to encounter, as well as all scheduled appts
else {
appointments.removeIf(appointment -> (appointment.getFulfillingEncounters() == null
|| !appointment.getFulfillingEncounters().contains(context.getExistingEncounter()))
&& appointment.getStatus() != AppointmentStatus.Scheduled);
}
}
}

Expand All @@ -68,8 +74,8 @@ public Collection<FormSubmissionError> validateSubmission(FormEntryContext conte
@Override
public void handleSubmission(FormEntrySession session, HttpServletRequest submission) {
List<String> selectedAppointmentUuids = (List<String>) appointmentsWidget.getValue(session.getContext(), submission);
List<Appointment> appointmentsToMarkCheckedIn = new ArrayList<>();
List<Appointment> appointmentsToDisassociateFromEncounter = new ArrayList<>();
List<Object> appointmentsToMarkCheckedIn = new ArrayList<>();
List<Object> appointmentsToDisassociateFromEncounter = new ArrayList<>();

// find appointments that need to be marked as checked in
for (String uuid : selectedAppointmentUuids) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ public AppointmentsWidget(List<Appointment> appointments, FormEntryContext conte
String fieldName = context.registerWidget(this);

// note that we are relying on the register widget to generate a single unique field name,
// and then we are appending _1, _2, _3, etc to that field name to create unique field names for each checkbox
// and then we are appending the uuid to that field name to create unique field names for each checkbox
// this is to ensure that this widget consistently increments the field name sequential value only once,
// otherwise, if the number of matches appointments changed between when the form was opened and the form was saved,
// widget names would be inconsistent, wreaking havoc on the form
int i = 1;
for (Appointment appointment : appointments) {

// compare dates so that we can highlight any that match the encounter darw
Expand All @@ -51,7 +50,7 @@ && new DateTime(appointment.getStartDateTime()).withTimeAtStartOfDay()
&& appointment.getFulfillingEncounters().contains(context.getExistingEncounter())) {
checkboxWidget.setInitialValue(appointment.getUuid());
}
context.registerWidget(checkboxWidget, fieldName + "_" + i++);
context.registerWidget(checkboxWidget, fieldName + "_" + appointment.getUuid());
checkboxWidgets.add(checkboxWidget);
}

Expand Down

0 comments on commit f3e379b

Please sign in to comment.