From 482d0facda3f2242b0a5935092701d74fdc3ab71 Mon Sep 17 00:00:00 2001 From: Kavitha S Date: Wed, 14 Feb 2024 01:35:23 +0530 Subject: [PATCH] Kavitha | add api to fetch slots by patient list with custom includes --- .../openmrs/module/ipd/api/dao/SlotDAO.java | 6 ++ .../ipd/api/dao/impl/HibernateSlotDAO.java | 80 ++++++++++++++++++ .../module/ipd/api/service/SlotService.java | 7 ++ .../ipd/api/service/impl/SlotServiceImpl.java | 15 ++++ .../impl/HibernateSlotDAOIntegrationTest.java | 53 ++++++++++++ .../api/service/impl/SlotServiceImplTest.java | 52 ++++++++++++ .../resources/scheduleMedicationsTestData.xml | 41 ++++++++++ .../PatientMedicationSummaryResponse.java | 35 ++++++++ .../PrescribedOrderSlotSummaryResponse.java | 36 +++++++++ .../ipd/controller/IPDScheduleController.java | 24 ++++++ .../ipd/model/PatientMedicationSummary.java | 19 +++++ .../ipd/model/PrescribedOrderSlotSummary.java | 20 +++++ .../ipd/service/IPDScheduleService.java | 3 + .../service/impl/IPDScheduleServiceImpl.java | 81 +++++++++++++++++++ 14 files changed, 472 insertions(+) create mode 100644 api/src/test/resources/scheduleMedicationsTestData.xml create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java create mode 100644 omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java index 6966329..71a5837 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.dao; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; @@ -32,4 +33,9 @@ public interface SlotDAO { List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); + List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate); + + List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate); + + List getSlotDurationForPatientsByOrder(List orders, List serviceTypes); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java index 62ca526..9a2003f 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAO.java @@ -2,6 +2,7 @@ import org.hibernate.query.Query; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; import org.openmrs.module.ipd.api.model.Reference; @@ -134,4 +135,83 @@ public List getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subj return query.getResultList(); } + + @Override + public List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate) { + Query query = sessionFactory.getCurrentSession() + .createQuery("SELECT slot FROM Slot slot \n" + + "INNER JOIN slot.schedule.subject reference \n" + + "INNER JOIN slot.schedule.visit visit \n" + + "WHERE (slot.startDateTime BETWEEN :startDate and :endDate) \n" + + "and slot.voided=0 \n" + + "and visit.stopDatetime is NULL \n" + + "and reference.type = 'org.openmrs.Patient' \n" + + "and reference.targetUuid in (:patientUuidList)"); + + query.setParameterList("patientUuidList", patientUuidList); + query.setParameter("startDate", localStartDate); + query.setParameter("endDate", localEndDate); + + return query.getResultList(); + } + + @Override + public List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate) { + String maxDateTimeSubquery = "SELECT s.order, MAX(s.startDateTime) AS maxStartDateTime " + + "FROM Slot s " + + "INNER JOIN s.schedule.subject reference " + + "INNER JOIN s.schedule.visit visit " + + "WHERE s.startDateTime < :startDate " + + "AND s.voided = 0 " + + "AND visit.stopDatetime IS NULL " + + "AND reference.type = 'org.openmrs.Patient' " + + "AND reference.targetUuid IN (:patientUuidList) " + + "GROUP BY s.order"; + + String latestPreviousSlotsQuery = "SELECT slot " + + "FROM Slot slot " + + "INNER JOIN slot.schedule.subject reference " + + "INNER JOIN slot.schedule.visit visit " + + "WHERE slot.startDateTime < :startDate " + + "AND slot.voided = 0 " + + "AND visit.stopDatetime IS NULL " + + "AND reference.type = 'org.openmrs.Patient' " + + "AND reference.targetUuid IN (:patientUuidList) " + + "AND (slot.order, slot.startDateTime) IN " + + "( " + maxDateTimeSubquery + " ) "; + + Query query = sessionFactory.getCurrentSession() + .createQuery(latestPreviousSlotsQuery); + + query.setParameterList("patientUuidList", patientUuidList); + query.setParameter("startDate", localStartDate); + + return query.getResultList(); + } + + @Override + public List getSlotDurationForPatientsByOrder(List orders, List serviceTypes) { + Query query = sessionFactory.getCurrentSession() + .createQuery("SELECT \n" + + " slot.order AS order,\n" + + " MIN(slot.startDateTime) AS minStartDateTime,\n" + + " MAX(slot.startDateTime) AS maxStartDateTime\n" + + "FROM\n" + + " Slot slot\n" + + "INNER JOIN\n" + + " slot.schedule.subject reference\n" + + "INNER JOIN\n" + + " slot.schedule.visit visit \n" + + "WHERE\n" + + " slot.voided = 0\n" + + " AND slot.serviceType IN (:serviceTypes)\n" + + " AND visit.stopDatetime is NULL \n" + + " AND slot.order IN (:orders)\n" + + "GROUP BY\n" + + " slot.order"); + + query.setParameterList("orders", orders); + query.setParameterList("serviceTypes", serviceTypes); + return query.getResultList(); + } } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java index 467b04e..5e62c4e 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/SlotService.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.Visit; import org.openmrs.module.ipd.api.model.Reference; import org.openmrs.module.ipd.api.model.Slot; @@ -37,4 +38,10 @@ public interface SlotService extends OpenmrsService { List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit); + + List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate); + + List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate); + + List getSlotDurationForPatientsByOrder(List orders, List serviceTypes); } diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java index 4ca8458..266c25a 100644 --- a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImpl.java @@ -1,6 +1,7 @@ package org.openmrs.module.ipd.api.service.impl; import org.openmrs.Concept; +import org.openmrs.Order; import org.openmrs.api.ConceptService; import org.openmrs.api.context.Context; import org.openmrs.Visit; @@ -95,4 +96,18 @@ public List getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference public List getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate, Visit visit) { return slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(subject, localStartDate, localEndDate, visit); } + + @Override + public List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, LocalDateTime localEndDate) { + return slotDAO.getSlotsForPatientListByTime(patientUuidList, localStartDate, localEndDate); + } + + @Override + public List getImmediatePreviousSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate) { + return slotDAO.getImmediatePreviousSlotsForPatientListByTime(patientUuidList, localStartDate); + } + + public List getSlotDurationForPatientsByOrder(List orders, List serviceTypes) { + return slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes); + } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java index df0a0cf..231d5b2 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateSlotDAOIntegrationTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Assertions; import org.openmrs.Concept; import org.openmrs.DrugOrder; +import org.openmrs.Order; import org.openmrs.Patient; import org.openmrs.Visit; import org.openmrs.VisitType; @@ -21,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -428,4 +430,55 @@ public void shouldGetTheSavedSlotsForPatientBySubjectReferenceAndAGivenTimeFrame sessionFactory.getCurrentSession().delete(visit); } + + @Test + public void shouldGetSlotsForPatientListByTime() { + executeDataSet("scheduleMedicationsTestData.xml"); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startTime = LocalDateTime.parse("2024-01-28 11:00:00", formatter); + LocalDateTime endTime = LocalDateTime.parse("2024-01-29 11:00:00", formatter); + List patientUuids = new ArrayList<>(); + patientUuids.add("75e04d42-3ca8-11e3-bf2b-0800271c1b75"); + + List slotsForPatientListByTime = slotDAO.getSlotsForPatientListByTime(patientUuids, startTime, endTime); + + Assertions.assertEquals(3, slotsForPatientListByTime.size()); + } + + @Test + public void shouldGetImmediatePreviousSlotsForPatientListByTime() { + executeDataSet("scheduleMedicationsTestData.xml"); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startTime = LocalDateTime.parse("2024-01-28 11:00:00", formatter); + List patientUuids = new ArrayList<>(); + patientUuids.add("75e04d42-3ca8-11e3-bf2b-0800271c1b75"); + + List previousSlots = slotDAO.getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime); + + Assertions.assertEquals(1, previousSlots.size()); + } + + @Test + public void shouldGetSlotDurationForPatientsByOrder() { + executeDataSet("scheduleMedicationsTestData.xml"); + + List orders = new ArrayList<>(); + Order order = Context.getOrderService().getOrderByUuid("6d0ae386-707a-4629-9850-f15206e63ab0"); + orders.add(order); + List serviceTypes = new ArrayList<>(); + serviceTypes.add(Context.getConceptService().getConceptByName("MedicationRequest")); + + List slotsDuration = slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes); + + Assertions.assertEquals(1, slotsDuration.size()); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startTime = LocalDateTime.parse("2024-01-27 20:00:00", formatter); + LocalDateTime endTime = LocalDateTime.parse("2024-01-29 08:00:00", formatter); + + Assertions.assertEquals(startTime, slotsDuration.get(0)[1]); + Assertions.assertEquals(endTime, slotsDuration.get(0)[2]); + } } diff --git a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java index 6542c40..137ca74 100644 --- a/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java +++ b/api/src/test/java/org/openmrs/module/ipd/api/service/impl/SlotServiceImplTest.java @@ -8,6 +8,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.openmrs.Concept; import org.openmrs.ConceptName; +import org.openmrs.Order; import org.openmrs.Patient; import org.openmrs.Visit; import org.openmrs.module.ipd.api.dao.SlotDAO; @@ -137,4 +138,55 @@ public void shouldInvokeGetSlotsBySubjectReferenceAndAdministeredTimeWithGivenTi Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime, visit); } + + @Test + public void shouldInvokeGetSlotsForPatientListByTime() { + List slots = new ArrayList<>(); + LocalDateTime startTime= LocalDateTime.now(); + LocalDateTime endTime = startTime.plusHours(3); + List patientUuids = new ArrayList<>(); + patientUuids.add("patientUuid1"); + patientUuids.add("patientUuid2"); + + Mockito.when(slotDAO.getSlotsForPatientListByTime(patientUuids, startTime, endTime)).thenReturn(slots); + slotService.getSlotsForPatientListByTime(patientUuids, startTime, endTime); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotsForPatientListByTime(patientUuids, startTime, endTime); + } + + @Test + public void shouldInvokeGetImmediatePreviousSlotsForPatientListByTime() { + List slots = new ArrayList<>(); + LocalDateTime startTime= LocalDateTime.now(); + List patientUuids = new ArrayList<>(); + patientUuids.add("patientUuid1"); + patientUuids.add("patientUuid2"); + + Mockito.when(slotDAO.getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime)).thenReturn(slots); + slotService.getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime); + + Mockito.verify(slotDAO, Mockito.times(1)).getImmediatePreviousSlotsForPatientListByTime(patientUuids, startTime); + } + + @Test + public void shouldInvokeGetSlotDurationForPatientsByOrder() { + List slotDurationObjects = new ArrayList<>(); + List orders = new ArrayList<>(); + Order order = new Order(); + order.setUuid("orderUuid1"); + orders.add(order); + order = new Order(); + order.setUuid("orderUuid2"); + orders.add(order); + + List serviceTypes = new ArrayList<>(); + Concept concept = new Concept(); + concept.setUuid("serviceType1"); + serviceTypes.add(concept); + + Mockito.when(slotDAO.getSlotDurationForPatientsByOrder(orders, serviceTypes)).thenReturn(slotDurationObjects); + slotService.getSlotDurationForPatientsByOrder(orders, serviceTypes); + + Mockito.verify(slotDAO, Mockito.times(1)).getSlotDurationForPatientsByOrder(orders, serviceTypes); + } } \ No newline at end of file diff --git a/api/src/test/resources/scheduleMedicationsTestData.xml b/api/src/test/resources/scheduleMedicationsTestData.xml new file mode 100644 index 0000000..920b1d3 --- /dev/null +++ b/api/src/test/resources/scheduleMedicationsTestData.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java new file mode 100644 index 0000000..d7b3509 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/PatientMedicationSummaryResponse.java @@ -0,0 +1,35 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.model.PatientMedicationSummary; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PatientMedicationSummaryResponse { + + private String patientUuid; + private List prescribedOrderSlots; + private List emergencyMedicationSlots; + + public static PatientMedicationSummaryResponse createFrom(PatientMedicationSummary patientMedicationSummary) { + List prescribedOrderSlots = patientMedicationSummary.getPrescribedOrderSlots() != null + ? patientMedicationSummary.getPrescribedOrderSlots().stream().map(PrescribedOrderSlotSummaryResponse::createFrom).collect(Collectors.toList()) + : null; + List emergencyMedicationSlots = patientMedicationSummary.getEmergencyMedicationSlots() != null + ? patientMedicationSummary.getEmergencyMedicationSlots().stream().map(MedicationSlotResponse::createFrom).collect(Collectors.toList()) + : null; + return PatientMedicationSummaryResponse.builder() + .patientUuid(patientMedicationSummary.getPatientUuid()) + .prescribedOrderSlots(prescribedOrderSlots) + .emergencyMedicationSlots(emergencyMedicationSlots) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java new file mode 100644 index 0000000..bff5a15 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/PrescribedOrderSlotSummaryResponse.java @@ -0,0 +1,36 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.module.ipd.model.PrescribedOrderSlotSummary; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrescribedOrderSlotSummaryResponse { + + private String orderUuid; + private List currentSlots; + private MedicationSlotResponse previousSlot; + private Long initialSlotStartTime; + private Long finalSlotStartTime; + + public static PrescribedOrderSlotSummaryResponse createFrom(PrescribedOrderSlotSummary prescribedOrderSlotsSummary){ + MedicationSlotResponse previousSlot = prescribedOrderSlotsSummary.getPreviousSlot() != null + ? MedicationSlotResponse.createFrom(prescribedOrderSlotsSummary.getPreviousSlot()) + : null; + return PrescribedOrderSlotSummaryResponse.builder() + .orderUuid(prescribedOrderSlotsSummary.getOrderUuid()) + .currentSlots(prescribedOrderSlotsSummary.getCurrentSlots().stream().map(slot -> MedicationSlotResponse.createFrom(slot)).collect(Collectors.toList())) + .previousSlot(previousSlot) + .initialSlotStartTime(prescribedOrderSlotsSummary.getInitialSlotStartTime()) + .finalSlotStartTime(prescribedOrderSlotsSummary.getFinalSlotStartTime()) + .build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java index 153698a..d98a1d5 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDScheduleController.java @@ -13,8 +13,10 @@ import org.openmrs.module.ipd.api.service.ScheduleService; import org.openmrs.module.ipd.contract.MedicationScheduleResponse; import org.openmrs.module.ipd.contract.MedicationSlotResponse; +import org.openmrs.module.ipd.contract.PatientMedicationSummaryResponse; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.contract.ScheduleMedicationResponse; +import org.openmrs.module.ipd.model.PatientMedicationSummary; import org.openmrs.module.ipd.service.IPDScheduleService; import org.openmrs.module.webservices.rest.web.RestConstants; import org.openmrs.module.webservices.rest.web.RestUtil; @@ -126,6 +128,28 @@ public ResponseEntity getMedicationSlotsByOrderUuids(@RequestParam(value } } + @RequestMapping(value = "type/medication/patientsMedicationSummary", method = RequestMethod.GET, params = {"patientUuids", "startTime", "endTime"}) + @ResponseBody + public ResponseEntity getSlotsForPatientsAndTime(@RequestParam(value = "patientUuids") List patientUuidList, + @RequestParam(value = "startTime") Long startTime, + @RequestParam(value = "endTime") Long endTime, + @RequestParam(value = "includePreviousSlot",required = false) Boolean includePreviousSlot, + @RequestParam(value = "includeSlotDuration",required = false) Boolean includeSlotDuration) { + try { + if (startTime != null && endTime != null) { + LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime); + LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime); + List patientMedicationSummaries = ipdScheduleService.getSlotsForPatientListByTime(patientUuidList, + localStartDate, localEndDate, includePreviousSlot, includeSlotDuration); + return new ResponseEntity<>(patientMedicationSummaries.stream().map(PatientMedicationSummaryResponse::createFrom).collect(Collectors.toList()), OK); + } + throw new Exception(); + } catch (Exception e) { + log.error("Runtime error while fetching patient medication summaries", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + private List constructResponse(List slots, Visit visit) { Schedule schedule = scheduleService.getScheduleByVisit(visit); diff --git a/omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java b/omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java new file mode 100644 index 0000000..e9323fd --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/model/PatientMedicationSummary.java @@ -0,0 +1,19 @@ +package org.openmrs.module.ipd.model; + +import lombok.*; +import org.openmrs.module.ipd.api.model.Slot; + +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PatientMedicationSummary { + + private String patientUuid; + private List prescribedOrderSlots; + private List emergencyMedicationSlots; + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java b/omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java new file mode 100644 index 0000000..4592f07 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/model/PrescribedOrderSlotSummary.java @@ -0,0 +1,20 @@ +package org.openmrs.module.ipd.model; + +import lombok.*; +import org.openmrs.module.ipd.api.model.Slot; + +import java.util.List; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PrescribedOrderSlotSummary { + + private String orderUuid; + private List currentSlots; + private Slot previousSlot; + private Long initialSlotStartTime; + private Long finalSlotStartTime; +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java index 6e60a47..c220b51 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDScheduleService.java @@ -7,6 +7,7 @@ import org.openmrs.module.ipd.api.model.ServiceType; import org.openmrs.module.ipd.api.model.Slot; import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; +import org.openmrs.module.ipd.model.PatientMedicationSummary; import java.time.LocalDate; import java.time.LocalDateTime; @@ -20,4 +21,6 @@ public interface IPDScheduleService { Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest); List getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime, Visit visit); void handlePostProcessEncounterTransaction(Encounter encounter, EncounterTransaction encounterTransaction); + List getSlotsForPatientListByTime(List patientUuidList, LocalDateTime localStartDate, + LocalDateTime localEndDate, Boolean includePreviousSlot, Boolean includeSlotDuration); } \ No newline at end of file diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java index a0b7140..ecca043 100644 --- a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDScheduleServiceImpl.java @@ -18,6 +18,8 @@ import org.openmrs.module.ipd.contract.ScheduleMedicationRequest; import org.openmrs.module.ipd.factory.ScheduleFactory; import org.openmrs.module.ipd.factory.SlotFactory; +import org.openmrs.module.ipd.model.PrescribedOrderSlotSummary; +import org.openmrs.module.ipd.model.PatientMedicationSummary; import org.openmrs.module.ipd.service.IPDScheduleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -144,6 +146,85 @@ public void handlePostProcessEncounterTransaction(Encounter encounter, Encounter } } + @Override + public List getSlotsForPatientListByTime(List patientUuidList, + LocalDateTime localStartDate, + LocalDateTime localEndDate, + Boolean includePreviousSlot, + Boolean includeSlotDuration) { + List slots = slotService.getSlotsForPatientListByTime(patientUuidList, localStartDate, localEndDate); + + List previousSlots = null; + if (includePreviousSlot == true) { + previousSlots = slotService.getImmediatePreviousSlotsForPatientListByTime(patientUuidList, localStartDate); + } + + List slotsDuration = null; + if (includeSlotDuration == true) { + List orders = slots.stream() + .map(Slot::getOrder) + .filter(order -> order != null) + .distinct() + .collect(Collectors.toList()); + List serviceTypes = new ArrayList<>(); + serviceTypes.add(Context.getConceptService().getConceptByName(ServiceType.MEDICATION_REQUEST.conceptName())); + serviceTypes.add(Context.getConceptService().getConceptByName(ServiceType.AS_NEEDED_MEDICATION_REQUEST.conceptName())); + + slotsDuration = slotService.getSlotDurationForPatientsByOrder(orders, serviceTypes); + } + + return groupSlotsByMedicationsAndPatients(slots, previousSlots, slotsDuration); + } + + private List groupSlotsByMedicationsAndPatients(List currentSlots, + List previousSlots, + List slotsDuration) { + + Map>> groupedSlots = currentSlots.stream() + .collect(Collectors.groupingBy( + slot -> slot.getSchedule().getSubject().getTargetUuid(), + Collectors.groupingBy( + slot -> slot.getOrder() != null ? slot.getOrder().getUuid() : "emergencyMedications" + ) + )); + + List patientMedicationsList = groupedSlots.entrySet().stream() + .map(entry -> { + PatientMedicationSummary patientMedicationSummary = new PatientMedicationSummary(); + patientMedicationSummary.setPatientUuid(entry.getKey()); + List prescribedOrderSlotsSummaryList = entry.getValue().entrySet().stream() + .filter(subEntry -> subEntry.getKey() != null) + .map(subEntry -> { + PrescribedOrderSlotSummary prescribedOrderSlotSummary = new PrescribedOrderSlotSummary(); + prescribedOrderSlotSummary.setOrderUuid(subEntry.getKey()); + prescribedOrderSlotSummary.setCurrentSlots(subEntry.getValue()); + if (previousSlots != null) { + prescribedOrderSlotSummary.setPreviousSlot(previousSlots.stream() + .filter(slot -> slot.getOrder().getUuid().equals(subEntry.getKey())) + .findFirst() + .orElse(null)); + } + if (slotsDuration != null) { + Object[] durationObj = slotsDuration.stream() + .filter(item -> ((Order) item[0]).getUuid().equals(subEntry.getKey())) + .findFirst() + .orElse(null); + prescribedOrderSlotSummary.setInitialSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc((LocalDateTime) durationObj[1])); + prescribedOrderSlotSummary.setFinalSlotStartTime(DateTimeUtil.convertLocalDateTimeToUTCEpoc((LocalDateTime) durationObj[2])); + } + return prescribedOrderSlotSummary; + }) + .collect(Collectors.toList()); + patientMedicationSummary.setPrescribedOrderSlots(prescribedOrderSlotsSummaryList); + patientMedicationSummary.setEmergencyMedicationSlots(entry.getValue().get("emergencyMedications")); + + return patientMedicationSummary; + }) + .collect(Collectors.toList()); + + return patientMedicationsList; + } + private void handleDrugOrderStop(EncounterTransaction encounterTransaction){ List stoppedDrugOrders = encounterTransaction.getDrugOrders().stream().filter(drugOrder -> drugOrder.getDateStopped() !=null).collect(Collectors.toList()); String patientUuid = encounterTransaction.getPatientUuid();