From bf2e6c813c9f371c0fed691d28efc57515cf291d Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Mon, 17 Jun 2024 19:05:47 -0400 Subject: [PATCH 1/3] O3-3193: REST API for EMR API ADT functionality --- .../controller/InpatientVisitsController.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java diff --git a/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java new file mode 100644 index 00000000..95292ec6 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java @@ -0,0 +1,74 @@ +package org.openmrs.module.emrapi.web.controller; + +import java.util.ArrayList; +import java.util.List; + +import org.joda.time.DateTime; +import org.joda.time.Minutes; +import org.openmrs.Location; +import org.openmrs.Visit; +import org.openmrs.module.emrapi.adt.AdtService; +import org.openmrs.module.emrapi.visit.VisitDomainWrapper; +import org.openmrs.module.webservices.rest.SimpleObject; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping(value = "/rest/emrapi/inpatient") +public class InpatientVisitsController { + + @Autowired + private AdtService adtService; + + @RequestMapping(method = RequestMethod.GET, value = "/visits") + @ResponseBody + public List getInpatientVisits(@RequestParam(value = "currentLocation") Location currentLocation) { + + // TODO expand to allow null current location + + // TODO handle null response if possible + // TODO this getInpatentVisits method is almost certainly not performant enough for production use and will likely need to be refactored into a HQL query + List visits = adtService.getInpatientVisits(adtService.getLocationThatSupportsVisits(currentLocation), currentLocation); + + // TODO type this? + List response = new ArrayList(); + + for (VisitDomainWrapper visit : visits) { + SimpleObject inpatientVisit = new SimpleObject(); + inpatientVisit.put("visit", ConversionUtil.convertToRepresentation(visit.getVisit(), Representation.DEFAULT)); + inpatientVisit.put("patient", ConversionUtil.convertToRepresentation(visit.getVisit().getPatient(), Representation.DEFAULT)); + inpatientVisit.put("currentLocation", ConversionUtil.convertToRepresentation(currentLocation, Representation.DEFAULT)); + inpatientVisit.put("timeSinceAdmissionInMinutes", Minutes.minutesBetween(new DateTime(visit.getAdmissionEncounter().getEncounterDatetime()), new DateTime()).getMinutes()); + inpatientVisit.put("timeOnWardInMinutes", Minutes.minutesBetween(new DateTime(visit.getLatestAdtEncounter().getEncounterDatetime()), new DateTime()).getMinutes()); // TODO: assumption, an ADT ecounter always results in change of ward? + response.add(inpatientVisit); + } + + return response; + } + + @RequestMapping(method = RequestMethod.GET, value = "/admissionRequests") + @ResponseBody + public List getVisitsAwaitingAdmission(@RequestParam("admissionLocation") Location admissionLocation) { + + // TODO note that this service method *only* returns admission requests, while we will need to expand this to include transfer requests (which will be slightly non-trivial) + // TODO note also that this service method does *not* actually limit by admission location; we will need to expand the underlying service method/hql query to do this + List visits = adtService.getVisitsAwaitingAdmission(admissionLocation, null, null); + List response = new ArrayList(); + for (Visit visit : visits) { + SimpleObject inpatientVisit = new SimpleObject(); + inpatientVisit.put("visit", ConversionUtil.convertToRepresentation(visit, Representation.DEFAULT)); + inpatientVisit.put("patient", ConversionUtil.convertToRepresentation(visit.getPatient(), Representation.DEFAULT)); + response.add(inpatientVisit); + } + return response; + } +} + + + From 002dc30cac66187b931033f486f90891338f7ce1 Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Thu, 20 Jun 2024 18:49:14 -0400 Subject: [PATCH 2/3] O3-3193: REST API for EMR API ADT functionality --- .../openmrs/module/emrapi/adt/AdtService.java | 9 ++++ .../module/emrapi/adt/AdtServiceImpl.java | 7 +++ .../emrapi/visit/VisitDomainWrapper.java | 32 +++++++++++++ .../controller/InpatientVisitsController.java | 46 ++++++++++++++++--- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java index d16be9fd..e66af4f0 100644 --- a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java +++ b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java @@ -344,5 +344,14 @@ VisitDomainWrapper createRetrospectiveVisit(Patient patient, Location location, * @param visitIds - if non-null, only returns matches for visits with the given ids * @return List of the matching visits */ + // TODO expand this to take in an admissionLocation parameter and limit to admissions at that location List getVisitsAwaitingAdmission(Location location, Collection patientIds, Collection visitIds); + + /** + * Returns all patient awaiting transfer + * @param location - if non-null, only checks awaiting transfers at the visit location associated with this location TODO do we need this? + * @param transferLocation - if non-null, only returns matches for patients awaiting transfer to this location + * @return List of the matching visits< + */ + List getVisitsAwaitingTransfer(Location location, Location transferLocation); } diff --git a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java index 08a0abf7..f6388f6d 100644 --- a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java @@ -917,4 +917,11 @@ public List getVisitsAwaitingAdmission(Location location, Collection getVisitsAwaitingTransfer(Location location, Location transferLocation) { + // TODO implement! + return Collections.emptyList(); + } } diff --git a/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java b/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java index 0de780e2..c84cd82f 100644 --- a/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java +++ b/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java @@ -18,6 +18,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.joda.time.DateMidnight; +import org.joda.time.DateTime; +import org.joda.time.Minutes; import org.openmrs.Encounter; import org.openmrs.EncounterType; import org.openmrs.Location; @@ -54,6 +56,7 @@ import static java.util.Collections.EMPTY_LIST; import static java.util.Collections.reverseOrder; import static java.util.Collections.sort; +import static org.apache.commons.collections.CollectionUtils.filter; import static org.apache.commons.collections.CollectionUtils.find; import static org.apache.commons.collections.CollectionUtils.select; @@ -532,6 +535,35 @@ public Location getInpatientLocation(Date onDate) { return null; } + public Integer timeSinceAdmissionInMinutes() { + if (getAdmissionEncounter() == null) { + return null; + } else { + return Minutes.minutesBetween(new DateTime(getAdmissionEncounter().getEncounterDatetime()), new DateTime()).getMinutes(); + } + } + + public Integer timeAtLocationInMinutes() { + EncounterType admissionEncounterType = emrApiProperties.getAdmissionEncounterType(); + EncounterType transferEncounterType = emrApiProperties.getTransferWithinHospitalEncounterType(); + + Location ward = null; + Integer time = null; + + for (Encounter encounter : getSortedEncounters(SortOrder.MOST_RECENT_FIRST)) { + if (encounter.getEncounterType().equals(admissionEncounterType) || encounter.getEncounterType().equals(transferEncounterType)) { + time = Minutes.minutesBetween(new DateTime(encounter.getEncounterDatetime()), new DateTime()).getMinutes(); + if (ward == null) { + ward = encounter.getLocation(); + } + else if (!ward.equals(encounter.getLocation())) { + break; + } + } + } + return time; + } + public Date getStartDatetime() { return visit.getStartDatetime(); } diff --git a/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java index 95292ec6..00a843b9 100644 --- a/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java +++ b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java @@ -3,10 +3,9 @@ import java.util.ArrayList; import java.util.List; -import org.joda.time.DateTime; -import org.joda.time.Minutes; import org.openmrs.Location; import org.openmrs.Visit; +import org.openmrs.module.emrapi.adt.AdtAction; import org.openmrs.module.emrapi.adt.AdtService; import org.openmrs.module.emrapi.visit.VisitDomainWrapper; import org.openmrs.module.webservices.rest.SimpleObject; @@ -44,8 +43,8 @@ public List getInpatientVisits(@RequestParam(value = "currentLocat inpatientVisit.put("visit", ConversionUtil.convertToRepresentation(visit.getVisit(), Representation.DEFAULT)); inpatientVisit.put("patient", ConversionUtil.convertToRepresentation(visit.getVisit().getPatient(), Representation.DEFAULT)); inpatientVisit.put("currentLocation", ConversionUtil.convertToRepresentation(currentLocation, Representation.DEFAULT)); - inpatientVisit.put("timeSinceAdmissionInMinutes", Minutes.minutesBetween(new DateTime(visit.getAdmissionEncounter().getEncounterDatetime()), new DateTime()).getMinutes()); - inpatientVisit.put("timeOnWardInMinutes", Minutes.minutesBetween(new DateTime(visit.getLatestAdtEncounter().getEncounterDatetime()), new DateTime()).getMinutes()); // TODO: assumption, an ADT ecounter always results in change of ward? + inpatientVisit.put("timeSinceAdmissionInMinutes", visit.timeSinceAdmissionInMinutes()); + inpatientVisit.put("timeAtLocationdInMinutes", visit.timeAtLocationInMinutes()); response.add(inpatientVisit); } @@ -55,19 +54,52 @@ public List getInpatientVisits(@RequestParam(value = "currentLocat @RequestMapping(method = RequestMethod.GET, value = "/admissionRequests") @ResponseBody public List getVisitsAwaitingAdmission(@RequestParam("admissionLocation") Location admissionLocation) { + return getVisitsAwaitingAdmissionHelper(admissionLocation); + } + + @RequestMapping(method = RequestMethod.GET, value = "/transferRequests") + @ResponseBody + public List getVisitsAwaitingTransfer(@RequestParam("transferLocation") Location transferLocation) { + return getVisitsAwaitingTransferHelper(transferLocation); + } + + @RequestMapping(method = RequestMethod.GET, value = "/admissionAndTransferRequests") + @ResponseBody + public List getVisitsAwaitingAdminstOrTransfer(@RequestParam("location") Location location) { + List response = getVisitsAwaitingAdmissionHelper(location); + response.addAll(getVisitsAwaitingTransferHelper(location)); + return response; + } + + private List getVisitsAwaitingAdmissionHelper(Location admissionLocation) { // TODO note that this service method *only* returns admission requests, while we will need to expand this to include transfer requests (which will be slightly non-trivial) // TODO note also that this service method does *not* actually limit by admission location; we will need to expand the underlying service method/hql query to do this List visits = adtService.getVisitsAwaitingAdmission(admissionLocation, null, null); - List response = new ArrayList(); + List visitObjects = new ArrayList(); for (Visit visit : visits) { SimpleObject inpatientVisit = new SimpleObject(); inpatientVisit.put("visit", ConversionUtil.convertToRepresentation(visit, Representation.DEFAULT)); inpatientVisit.put("patient", ConversionUtil.convertToRepresentation(visit.getPatient(), Representation.DEFAULT)); - response.add(inpatientVisit); + inpatientVisit.put("type", AdtAction.Type.ADMISSION); + visitObjects.add(inpatientVisit); } - return response; + return visitObjects; + } + + private List getVisitsAwaitingTransferHelper(Location transferLocation) { + List visits = adtService.getVisitsAwaitingTransfer(null, transferLocation); + List visitObjects = new ArrayList(); + for (Visit visit : visits) { + SimpleObject inpatientVisit = new SimpleObject(); + inpatientVisit.put("visit", ConversionUtil.convertToRepresentation(visit, Representation.DEFAULT)); + inpatientVisit.put("patient", ConversionUtil.convertToRepresentation(visit.getPatient(), Representation.DEFAULT)); + inpatientVisit.put("type", AdtAction.Type.TRANSFER); + visitObjects.add(inpatientVisit); + } + return visitObjects; } + } From 4bcea85716961cc609b11d4d822dcff007b90e2b Mon Sep 17 00:00:00 2001 From: Mark Goodrich Date: Fri, 21 Jun 2024 18:12:18 -0400 Subject: [PATCH 3/3] O3-3193: REST API for EMR API ADT functionality O3-3467: REST API - Create EmrApiConfig endpoint --- .../openmrs/module/emrapi/adt/AdtService.java | 5 +- .../module/emrapi/adt/AdtServiceImpl.java | 2 +- .../emrapi/visit/VisitDomainWrapper.java | 14 +- .../emrapi/visit/VisitDomainWrapperTest.java | 148 ++++++++++++++++++ .../controller/EmrApiConfigController.java | 27 ++++ .../controller/InpatientVisitsController.java | 22 +-- 6 files changed, 198 insertions(+), 20 deletions(-) create mode 100644 omod/src/main/java/org/openmrs/module/emrapi/web/controller/EmrApiConfigController.java diff --git a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java index e66af4f0..cdb9ecf6 100644 --- a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java +++ b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtService.java @@ -349,9 +349,8 @@ VisitDomainWrapper createRetrospectiveVisit(Patient patient, Location location, /** * Returns all patient awaiting transfer - * @param location - if non-null, only checks awaiting transfers at the visit location associated with this location TODO do we need this? - * @param transferLocation - if non-null, only returns matches for patients awaiting transfer to this location + * @param transferLocation - if non-null, only return matches for patients awaiting transfer to this location * @return List of the matching visits< */ - List getVisitsAwaitingTransfer(Location location, Location transferLocation); + List getVisitsAwaitingTransfer(Location transferLocation); } diff --git a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java index f6388f6d..69e42265 100644 --- a/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/emrapi/adt/AdtServiceImpl.java @@ -920,7 +920,7 @@ public List getVisitsAwaitingAdmission(Location location, Collection getVisitsAwaitingTransfer(Location location, Location transferLocation) { + public List getVisitsAwaitingTransfer(Location transferLocation) { // TODO implement! return Collections.emptyList(); } diff --git a/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java b/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java index c84cd82f..008aae90 100644 --- a/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java +++ b/api/src/main/java/org/openmrs/module/emrapi/visit/VisitDomainWrapper.java @@ -56,7 +56,6 @@ import static java.util.Collections.EMPTY_LIST; import static java.util.Collections.reverseOrder; import static java.util.Collections.sort; -import static org.apache.commons.collections.CollectionUtils.filter; import static org.apache.commons.collections.CollectionUtils.find; import static org.apache.commons.collections.CollectionUtils.select; @@ -535,15 +534,20 @@ public Location getInpatientLocation(Date onDate) { return null; } - public Integer timeSinceAdmissionInMinutes() { - if (getAdmissionEncounter() == null) { + public Integer getTimeSinceAdmissionInMinutes() { + if (!isAdmitted() || getAdmissionEncounter() == null) { return null; } else { return Minutes.minutesBetween(new DateTime(getAdmissionEncounter().getEncounterDatetime()), new DateTime()).getMinutes(); } } - public Integer timeAtLocationInMinutes() { + public Integer getTimeAtCurrentInpatientLocationInMinutes() { + + if (!isAdmitted()) { + return null; + } + EncounterType admissionEncounterType = emrApiProperties.getAdmissionEncounterType(); EncounterType transferEncounterType = emrApiProperties.getTransferWithinHospitalEncounterType(); @@ -552,13 +556,13 @@ public Integer timeAtLocationInMinutes() { for (Encounter encounter : getSortedEncounters(SortOrder.MOST_RECENT_FIRST)) { if (encounter.getEncounterType().equals(admissionEncounterType) || encounter.getEncounterType().equals(transferEncounterType)) { - time = Minutes.minutesBetween(new DateTime(encounter.getEncounterDatetime()), new DateTime()).getMinutes(); if (ward == null) { ward = encounter.getLocation(); } else if (!ward.equals(encounter.getLocation())) { break; } + time = Minutes.minutesBetween(new DateTime(encounter.getEncounterDatetime()), new DateTime()).getMinutes(); } } return time; diff --git a/api/src/test/java/org/openmrs/module/emrapi/visit/VisitDomainWrapperTest.java b/api/src/test/java/org/openmrs/module/emrapi/visit/VisitDomainWrapperTest.java index 4575a156..0ac0e5d4 100644 --- a/api/src/test/java/org/openmrs/module/emrapi/visit/VisitDomainWrapperTest.java +++ b/api/src/test/java/org/openmrs/module/emrapi/visit/VisitDomainWrapperTest.java @@ -1010,6 +1010,154 @@ public void shouldNotFailIfStopDatetimeNull() { assertNull(visitDomainWrapper.getStopDate()); } + @Test + public void timeSinceAdmissionInMinutes_shouldReturnTimeSinceAdmissionInMinutes() { + + EncounterType admitEncounterType = new EncounterType(); + EncounterType transferEncounterType = new EncounterType(); + + Location icu = new Location(); + + when(visit.getStartDatetime()).thenReturn(DateUtils.addHours(new Date(), -5)); + + EmrApiProperties props = mock(EmrApiProperties.class); + when(props.getAdmissionEncounterType()).thenReturn(admitEncounterType); + when(props.getTransferWithinHospitalEncounterType()).thenReturn(transferEncounterType); + visitDomainWrapper.setEmrApiProperties(props); + + Encounter admit = new Encounter(); + admit.setEncounterType(admitEncounterType); + admit.setEncounterDatetime(DateUtils.addHours(new Date(), -3)); + admit.setLocation(icu); + + Encounter transfer = new Encounter(); + transfer.setEncounterType(transferEncounterType); + transfer.setEncounterDatetime(DateUtils.addHours(new Date(), -2)); + transfer.setLocation(icu); + + Set encounters = new LinkedHashSet(); + encounters.add(admit); + encounters.add(transfer); + when(visit.getEncounters()).thenReturn(encounters); + + assertThat(visitDomainWrapper.getTimeSinceAdmissionInMinutes(), is(180)); + } + + @Test + public void timeSinceAdmissionInMinutes_shouldReturnNullIfPatientNeverAdmitted() { + when(visit.getStartDatetime()).thenReturn(DateUtils.addHours(new Date(), -5)); + assertNull(visitDomainWrapper.getTimeSinceAdmissionInMinutes()); + } + + @Test + public void timeSinceAdmissionInMinutes_shouldReturnNullIfPatientNoLongerAdmitted() { + + EncounterType admitEncounterType = new EncounterType(); + EncounterType exitFromInpatientEncounterType = new EncounterType(); + + Location icu = new Location(); + + when(visit.getStartDatetime()).thenReturn(DateUtils.addHours(new Date(), -5)); + + EmrApiProperties props = mock(EmrApiProperties.class); + when(props.getAdmissionEncounterType()).thenReturn(admitEncounterType); + when(props.getExitFromInpatientEncounterType()).thenReturn(exitFromInpatientEncounterType); + visitDomainWrapper.setEmrApiProperties(props); + + Encounter admit = new Encounter(); + admit.setEncounterType(admitEncounterType); + admit.setEncounterDatetime(DateUtils.addHours(new Date(), -3)); + admit.setLocation(icu); + + Encounter discharge = new Encounter(); + discharge.setEncounterType(exitFromInpatientEncounterType); + discharge.setEncounterDatetime(DateUtils.addHours(new Date(), -2)); + discharge.setLocation(icu); + + Set encounters = new LinkedHashSet(); + encounters.add(admit); + encounters.add(discharge); + when(visit.getEncounters()).thenReturn(encounters); + + assertNull(visitDomainWrapper.getTimeSinceAdmissionInMinutes()); + } + + @Test + public void timeAtCurrentInpatientLocationInMinutes_shouldReturnTimeAtCurrentInpatientLocationInMinutesEvenWhenMostRecentAdtEncounterDoesNotResultInLocationChange() { + + EncounterType admitEncounterType = new EncounterType(); + EncounterType transferEncounterType = new EncounterType(); + + Location icu = new Location(); + + when(visit.getStartDatetime()).thenReturn(DateUtils.addHours(new Date(), -5)); + + EmrApiProperties props = mock(EmrApiProperties.class); + when(props.getAdmissionEncounterType()).thenReturn(admitEncounterType); + when(props.getTransferWithinHospitalEncounterType()).thenReturn(transferEncounterType); + visitDomainWrapper.setEmrApiProperties(props); + + Encounter admit = new Encounter(); + admit.setEncounterType(admitEncounterType); + admit.setEncounterDatetime(DateUtils.addHours(new Date(), -3)); + admit.setLocation(icu); + + // not sure if this is a real use case, transfer to same location, but just in case + Encounter transfer = new Encounter(); + transfer.setEncounterType(transferEncounterType); + transfer.setEncounterDatetime(DateUtils.addHours(new Date(), -2)); + transfer.setLocation(icu); + + Set encounters = new LinkedHashSet(); + encounters.add(admit); + encounters.add(transfer); + when(visit.getEncounters()).thenReturn(encounters); + + assertThat(visitDomainWrapper.getTimeAtCurrentInpatientLocationInMinutes(), is(180)); + } + + + + @Test + public void timeAtCurrentInpatientLocationInMinutes_shouldReturnNullIfPatientNeverAdmitted() { + when(visit.getStartDatetime()).thenReturn(DateUtils.addHours(new Date(), -5)); + assertNull(visitDomainWrapper.getTimeAtCurrentInpatientLocationInMinutes()); + } + + @Test + public void timeAtCurrentInpatientLocationInMinutes_shouldReturnNullIfPatientNoLongerAdmitted() { + + EncounterType admitEncounterType = new EncounterType(); + EncounterType exitFromInpatientEncounterType = new EncounterType(); + + Location icu = new Location(); + + when(visit.getStartDatetime()).thenReturn(DateUtils.addHours(new Date(), -5)); + + EmrApiProperties props = mock(EmrApiProperties.class); + when(props.getAdmissionEncounterType()).thenReturn(admitEncounterType); + when(props.getExitFromInpatientEncounterType()).thenReturn(exitFromInpatientEncounterType); + visitDomainWrapper.setEmrApiProperties(props); + + Encounter admit = new Encounter(); + admit.setEncounterType(admitEncounterType); + admit.setEncounterDatetime(DateUtils.addHours(new Date(), -3)); + admit.setLocation(icu); + + Encounter discharge = new Encounter(); + discharge.setEncounterType(exitFromInpatientEncounterType); + discharge.setEncounterDatetime(DateUtils.addHours(new Date(), -2)); + discharge.setLocation(icu); + + Set encounters = new LinkedHashSet(); + encounters.add(admit); + encounters.add(discharge); + when(visit.getEncounters()).thenReturn(encounters); + + assertNull(visitDomainWrapper.getTimeAtCurrentInpatientLocationInMinutes()); + } + + private class ExpectedDiagnosis extends ArgumentMatcher { private Diagnosis expectedDiagnosis; diff --git a/omod/src/main/java/org/openmrs/module/emrapi/web/controller/EmrApiConfigController.java b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/EmrApiConfigController.java new file mode 100644 index 00000000..4a355668 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/EmrApiConfigController.java @@ -0,0 +1,27 @@ +package org.openmrs.module.emrapi.web.controller; + +import org.openmrs.module.emrapi.EmrApiProperties; +import org.openmrs.module.webservices.rest.SimpleObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping(value = "/rest/emrapi/configuration") +public class EmrApiConfigController { + + @Autowired + private EmrApiProperties emrApiProperties; + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public SimpleObject getEmrApiConfig() { + SimpleObject response = new SimpleObject(); + response.put("admissionEncounterType", emrApiProperties.getAdmissionEncounterType().getUuid()); + response.put("transferWithinHospitalEncounterType", emrApiProperties.getTransferWithinHospitalEncounterType().getUuid()); + response.put("exitFromInpatientEncounterTpye", emrApiProperties.getExitFromInpatientEncounterType().getUuid()); + return response; + } + +} diff --git a/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java index 00a843b9..069bafed 100644 --- a/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java +++ b/omod/src/main/java/org/openmrs/module/emrapi/web/controller/InpatientVisitsController.java @@ -29,22 +29,24 @@ public class InpatientVisitsController { @ResponseBody public List getInpatientVisits(@RequestParam(value = "currentLocation") Location currentLocation) { - // TODO expand to allow null current location + if (currentLocation == null) { + throw new IllegalArgumentException("currentLocation is required"); + } - // TODO handle null response if possible - // TODO this getInpatentVisits method is almost certainly not performant enough for production use and will likely need to be refactored into a HQL query List visits = adtService.getInpatientVisits(adtService.getLocationThatSupportsVisits(currentLocation), currentLocation); - - // TODO type this? List response = new ArrayList(); + if (visits == null) { + return response; + } + for (VisitDomainWrapper visit : visits) { SimpleObject inpatientVisit = new SimpleObject(); inpatientVisit.put("visit", ConversionUtil.convertToRepresentation(visit.getVisit(), Representation.DEFAULT)); inpatientVisit.put("patient", ConversionUtil.convertToRepresentation(visit.getVisit().getPatient(), Representation.DEFAULT)); inpatientVisit.put("currentLocation", ConversionUtil.convertToRepresentation(currentLocation, Representation.DEFAULT)); - inpatientVisit.put("timeSinceAdmissionInMinutes", visit.timeSinceAdmissionInMinutes()); - inpatientVisit.put("timeAtLocationdInMinutes", visit.timeAtLocationInMinutes()); + inpatientVisit.put("timeSinceAdmissionInMinutes", visit.getTimeSinceAdmissionInMinutes()); + inpatientVisit.put("timeAtInpatientLocationdInMinutes", visit.getTimeAtCurrentInpatientLocationInMinutes()); response.add(inpatientVisit); } @@ -71,10 +73,8 @@ public List getVisitsAwaitingAdminstOrTransfer(@RequestParam("loca return response; } - private List getVisitsAwaitingAdmissionHelper(Location admissionLocation) { - // TODO note that this service method *only* returns admission requests, while we will need to expand this to include transfer requests (which will be slightly non-trivial) - // TODO note also that this service method does *not* actually limit by admission location; we will need to expand the underlying service method/hql query to do this + // TODO note also that this service method does *not* actually limit by admission location; we will need to expand the underlying service method/hql query to do this, see: https://openmrs.atlassian.net/browse/O3-3464 List visits = adtService.getVisitsAwaitingAdmission(admissionLocation, null, null); List visitObjects = new ArrayList(); for (Visit visit : visits) { @@ -88,7 +88,7 @@ private List getVisitsAwaitingAdmissionHelper(Location admissionLo } private List getVisitsAwaitingTransferHelper(Location transferLocation) { - List visits = adtService.getVisitsAwaitingTransfer(null, transferLocation); + List visits = adtService.getVisitsAwaitingTransfer(transferLocation); List visitObjects = new ArrayList(); for (Visit visit : visits) { SimpleObject inpatientVisit = new SimpleObject();