Skip to content

Commit

Permalink
Changes to accomodate Drugchart view where we need to intended and ac…
Browse files Browse the repository at this point in the history
…tual administered time

Changes to accomodate Drugchart view where we need to intended and actual administered time
  • Loading branch information
kalai-tw authored Jan 12, 2024
1 parent 5ccfaad commit 28efc13
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 19 deletions.
3 changes: 3 additions & 0 deletions api/src/main/java/org/openmrs/module/ipd/api/dao/SlotDAO.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ public interface SlotDAO {
List<Slot> getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType);

List<Slot> getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate);

List<Slot> getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.openmrs.module.ipd.api.model.Slot;
import org.hibernate.SessionFactory;
import org.openmrs.api.db.DAOException;
import org.openmrs.module.ipd.api.util.DateTimeUtil;
import org.openmrs.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -109,4 +111,24 @@ public List<Slot> getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference

return query.getResultList();
}

@Override
public List<Slot> getSlotsBySubjectIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) {
Query query = sessionFactory.getCurrentSession()
.createQuery("SELECT slot FROM Slot slot " +
"LEFT JOIN slot.medicationAdministration medAdmin " +
"WHERE (slot.schedule.subject = :subject) AND " +
"(((slot.startDateTime BETWEEN :startDateTime AND :endDateTime) AND " +
"(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate or medAdmin is null)) OR " +
"(medAdmin is not null AND " +
"(medAdmin.administeredDateTime BETWEEN :startDate AND :endDate)))");

query.setParameter("subject", subject);
query.setParameter("startDateTime", localStartDate);
query.setParameter("endDateTime", localEndDate);
query.setParameter("startDate", DateTimeUtil.convertLocalDateTimeDate(localStartDate));
query.setParameter("endDate", DateTimeUtil.convertLocalDateTimeDate(localEndDate));

return query.getResultList();
}
}
4 changes: 2 additions & 2 deletions api/src/main/java/org/openmrs/module/ipd/api/model/Slot.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public class Slot extends BaseChangeableOpenmrsData {

public enum SlotStatus {
SCHEDULED,
MISSED,
NOT_DONE,
COMPLETED,
CANCELLED
STOPPED
}

@EqualsAndHashCode.Include
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ public interface SlotService extends OpenmrsService {
List<Slot> getSlotsByPatientAndVisitAndServiceType(Reference subject, Visit visit, Concept serviceType);

List<Slot> getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference reference, LocalDateTime localStartDate, LocalDateTime localEndDate);

List<Slot> getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@ public List<Slot> getSlotsByPatientAndVisitAndServiceType(Reference subject, Vis
public List<Slot> getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) {
return slotDAO.getSlotsBySubjectReferenceIdAndForTheGivenTimeFrame(subject, localStartDate, localEndDate);
}

@Override
public List<Slot> getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(Reference subject, LocalDateTime localStartDate, LocalDateTime localEndDate) {
return slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(subject, localStartDate, localEndDate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.openmrs.module.ipd.api.translators;

import org.hl7.fhir.r4.model.MedicationAdministration;
import org.openmrs.module.ipd.api.model.Slot;
import org.springframework.stereotype.Component;

@Component
public class MedicationAdministrationToSlotStatusTranslator {

public Slot.SlotStatus toSlotStatus(MedicationAdministration.MedicationAdministrationStatus medicationAdministrationStatus){
if (medicationAdministrationStatus.equals(MedicationAdministration.MedicationAdministrationStatus.COMPLETED)){
return Slot.SlotStatus.COMPLETED;
}
if (medicationAdministrationStatus.equals(MedicationAdministration.MedicationAdministrationStatus.NOTDONE)){
return Slot.SlotStatus.NOT_DONE;
}
if (medicationAdministrationStatus.equals(MedicationAdministration.MedicationAdministrationStatus.STOPPED)){
return Slot.SlotStatus.STOPPED;
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ public static long convertLocalDateTimeToUTCEpoc(LocalDateTime localDateTime) {
public static LocalDateTime convertDateToLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}

public static Date convertLocalDateTimeDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.openmrs.module.ipd.api.util;

public class IPDConstants {

public static final String IPD_VIEW_DRUG_CHART = "drugChart";

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import org.openmrs.DrugOrder;
import org.openmrs.Patient;
import org.openmrs.api.context.Context;
import org.openmrs.module.fhir2.apiext.dao.FhirMedicationAdministrationDao;
import org.openmrs.module.ipd.api.BaseIntegrationTest;
import org.openmrs.module.ipd.api.dao.ScheduleDAO;
import org.openmrs.module.ipd.api.dao.SlotDAO;
import org.openmrs.module.ipd.api.model.MedicationAdministration;
import org.openmrs.module.ipd.api.model.Reference;
import org.openmrs.module.ipd.api.model.Schedule;
import org.openmrs.module.ipd.api.model.Slot;
Expand All @@ -31,6 +33,9 @@ public class HibernateSlotDAOIntegrationTest extends BaseIntegrationTest {
@Autowired
private SessionFactory sessionFactory;

@Autowired
private FhirMedicationAdministrationDao<MedicationAdministration> medicationAdministrationDao;

@Test
public void shouldSaveTheSlotForPatientGivenPatientSchedule() {

Expand Down Expand Up @@ -238,4 +243,88 @@ public void shouldGetTheSavedSlotsForPatientByForReferenceIdAndServiceType() {
sessionFactory.getCurrentSession().delete(savedSlot2);
sessionFactory.getCurrentSession().delete(savedSchedule);
}

@Test
public void shouldGetTheSavedSlotsForPatientByAdministeredTime() {

String orderUuid = "921de0a3-05c4-444a-be03-e01b4c4b9142";
DrugOrder drugOrder = (DrugOrder) Context.getOrderService().getOrderByUuid(orderUuid);
DrugOrder drugOrder2 = (DrugOrder) Context.getOrderService().getOrderByUuid("921de0a3-05c4-444a-be03-e01b4c4b9143");
Reference patientReference = new Reference(Patient.class.getTypeName(), "2c33920f-7aa6-0000-998a-60412d8ff7d5");
Reference providerReference = new Reference(Patient.class.getTypeName(), "d869ad24-d2a0-4747-a888-fe55048bb7ce");
Concept testConcept = Context.getConceptService().getConceptByName("UNKNOWN");
LocalDateTime startDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStartDate());
LocalDateTime endDate = DateTimeUtil.convertDateToLocalDateTime(drugOrder.getEffectiveStopDate());

Schedule schedule = new Schedule();
schedule.setSubject(patientReference);
schedule.setActor(providerReference);
schedule.setStartDate(startDate);
schedule.setEndDate(endDate);
schedule.setServiceType(testConcept);

Schedule savedSchedule = scheduleDAO.saveSchedule(schedule);

LocalDateTime startTime = LocalDateTime.now();
LocalDateTime slot1StartTime = LocalDateTime.now().plusHours(1);
LocalDateTime slot2StartTime = LocalDateTime.now().plusDays(-1);
LocalDateTime medicationAdministeredTime= LocalDateTime.now().plusHours(3);
LocalDateTime medicationAdministeredTime2= LocalDateTime.now().plusDays(3);


MedicationAdministration medicationAdministration=new MedicationAdministration();
medicationAdministration.setStatus(testConcept);
medicationAdministration.setAdministeredDateTime(DateTimeUtil.convertLocalDateTimeDate(medicationAdministeredTime));
MedicationAdministration savedMedicationAdministration= medicationAdministrationDao.createOrUpdate(medicationAdministration);

MedicationAdministration medicationAdministration2=new MedicationAdministration();
medicationAdministration2.setStatus(testConcept);
medicationAdministration2.setAdministeredDateTime(DateTimeUtil.convertLocalDateTimeDate(medicationAdministeredTime2));
MedicationAdministration savedMedicationAdministration2= medicationAdministrationDao.createOrUpdate(medicationAdministration2);

Slot slot1 = new Slot();
slot1.setSchedule(savedSchedule);
slot1.setServiceType(testConcept);
slot1.setStartDateTime(slot1StartTime);
slot1.setOrder(drugOrder);

Slot slot2 = new Slot();
slot2.setSchedule(savedSchedule);
slot2.setServiceType(testConcept);
slot2.setStartDateTime(slot2StartTime);
slot2.setMedicationAdministration(savedMedicationAdministration);
slot2.setOrder(drugOrder2);

Slot slot3 = new Slot();
slot3.setSchedule(savedSchedule);
slot3.setServiceType(testConcept);
slot3.setStartDateTime(slot2StartTime);
slot3.setOrder(drugOrder);

Slot slot4 = new Slot();
slot4.setSchedule(savedSchedule);
slot4.setServiceType(testConcept);
slot4.setStartDateTime(slot1StartTime);
slot4.setMedicationAdministration(savedMedicationAdministration2);
slot4.setOrder(drugOrder);

Slot savedSlot1 = slotDAO.saveSlot(slot1);
Slot savedSlot2 = slotDAO.saveSlot(slot2);
Slot savedSlot3 = slotDAO.saveSlot(slot3);
Slot savedSlot4 = slotDAO.saveSlot(slot4);


List<Slot> slotsBySubjectReferenceIdAndServiceType = slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference,startTime,startTime.plusHours(6));

Assertions.assertEquals(2, slotsBySubjectReferenceIdAndServiceType.size());

sessionFactory.getCurrentSession().delete(savedMedicationAdministration);
sessionFactory.getCurrentSession().delete(savedMedicationAdministration2);
sessionFactory.getCurrentSession().delete(savedSlot1);
sessionFactory.getCurrentSession().delete(savedSlot2);
sessionFactory.getCurrentSession().delete(savedSlot3);
sessionFactory.getCurrentSession().delete(savedSlot4);
sessionFactory.getCurrentSession().delete(savedSchedule);

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.openmrs.module.ipd.api.model.Slot;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -119,4 +120,19 @@ public void shouldInvokeGetSlotsByForReferenceAndServiceTypeAndOrderUuidsWithGiv

Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectReferenceIdAndServiceTypeAndOrderUuids(patientReference, medicationRequestConcept, orderUuids);
}

@Test
public void shouldInvokeGetSlotsBySubjectReferenceAndAdministeredTimeWithGivenTimeFrame() {

List<Slot> slots = new ArrayList<>();
LocalDateTime startTime= LocalDateTime.now();
LocalDateTime endTime = startTime.plusHours(8);
Reference patientReference = new Reference(Patient.class.getTypeName(), "patientUuid");

Mockito.when(slotDAO.getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime)).thenReturn(slots);

slotService.getSlotsBySubjectReferenceIncludingAdministeredTimeFrame(patientReference,startTime,endTime);

Mockito.verify(slotDAO, Mockito.times(1)).getSlotsBySubjectIncludingAdministeredTimeFrame(patientReference, startTime, endTime);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ public class MedicationAdministrationRequest {
private String slotUuid;

public Date getAdministeredDateTimeAsLocaltime() {
return this.administeredDateTime != null ? new Date(TimeUnit.SECONDS.toMillis(this.administeredDateTime)): null;
return this.administeredDateTime != null ? new Date(TimeUnit.SECONDS.toMillis(this.administeredDateTime)): new Date();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import lombok.extern.slf4j.Slf4j;
import org.openmrs.module.ipd.api.model.Schedule;
import org.openmrs.module.ipd.api.model.Slot;
import org.openmrs.module.ipd.api.util.DateTimeUtil;
import org.openmrs.module.ipd.api.util.IPDConstants;
import org.openmrs.module.ipd.contract.MedicationScheduleResponse;
import org.openmrs.module.ipd.contract.MedicationSlotResponse;
import org.openmrs.module.ipd.contract.ScheduleMedicationRequest;
Expand All @@ -17,6 +19,7 @@
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -66,12 +69,14 @@ public ResponseEntity<Object> updateMedicationSchedule(@RequestBody ScheduleMedi
@RequestMapping(value = "type/medication", method = RequestMethod.GET, params = {"patientUuid", "startTime", "endTime"})
@ResponseBody
public ResponseEntity<Object> getMedicationSlotsByDate(@RequestParam(value = "patientUuid") String patientUuid,
@RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime) {
@RequestParam(value = "startTime") Long startTime, @RequestParam(value = "endTime") Long endTime,
@RequestParam(value = "view", required = false) String view) {
try {
if (startTime != null && endTime != null) {
LocalDateTime localStartDate = convertEpocUTCToLocalTimeZone(startTime);
LocalDateTime localEndDate = convertEpocUTCToLocalTimeZone(endTime);
List<Slot> slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate);
Boolean considerAdministeredTime = view!=null & IPDConstants.IPD_VIEW_DRUG_CHART.equals(view);
List<Slot> slots = ipdScheduleService.getMedicationSlotsForTheGivenTimeFrame(patientUuid, localStartDate, localEndDate,considerAdministeredTime);
return new ResponseEntity<>(constructResponse(slots), OK);
}
throw new Exception();
Expand Down Expand Up @@ -102,9 +107,9 @@ public ResponseEntity<Object> getMedicationSlotsByOrderUuids(@RequestParam(value
}
}


private List<MedicationScheduleResponse> constructResponse(List<Slot> slots) {
Map<Schedule, List<Slot>> slotsBySchedule = slots.stream().collect(Collectors.groupingBy(Slot::getSchedule));
return slotsBySchedule.entrySet().stream().map(entry -> createFrom(entry.getKey(), entry.getValue())).collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ public interface IPDScheduleService {
List<Slot> getMedicationSlots(String patientUuid, ServiceType serviceType);
List<Slot> getMedicationSlots(String patientUuid, ServiceType serviceType, List<String> orderUuids);
Schedule updateMedicationSchedule(ScheduleMedicationRequest scheduleMedicationRequest);
List<Slot> getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate);
List<Slot> getMedicationSlotsForTheGivenTimeFrame(String patientUuid, LocalDateTime localStartDate, LocalDateTime localEndDate,Boolean considerAdministeredTime);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.openmrs.module.ipd.api.model.Slot;
import org.openmrs.module.ipd.api.service.ScheduleService;
import org.openmrs.module.ipd.api.service.SlotService;
import org.openmrs.module.ipd.api.translators.MedicationAdministrationToSlotStatusTranslator;
import org.openmrs.module.ipd.api.util.DateTimeUtil;
import org.openmrs.module.ipd.contract.MedicationAdministrationRequest;
import org.openmrs.module.ipd.factory.MedicationAdministrationFactory;
Expand All @@ -39,20 +40,23 @@ public class IPDMedicationAdministrationServiceImpl implements IPDMedicationAdmi
private SlotService slotService;
private ScheduleService scheduleService;
private FhirMedicationAdministrationDao fhirMedicationAdministrationDao;
private MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator;

@Autowired
public IPDMedicationAdministrationServiceImpl(FhirMedicationAdministrationService fhirMedicationAdministrationService,
MedicationAdministrationTranslator medicationAdministrationTranslator,
MedicationAdministrationFactory medicationAdministrationFactory,
SlotFactory slotFactory, SlotService slotService, ScheduleService scheduleService,
FhirMedicationAdministrationDao fhirMedicationAdministrationDao) {
FhirMedicationAdministrationDao fhirMedicationAdministrationDao,
MedicationAdministrationToSlotStatusTranslator medicationAdministrationToSlotStatusTranslator) {
this.fhirMedicationAdministrationService = fhirMedicationAdministrationService;
this.medicationAdministrationTranslator = medicationAdministrationTranslator;
this.medicationAdministrationFactory = medicationAdministrationFactory;
this.slotFactory = slotFactory;
this.slotService = slotService;
this.scheduleService = scheduleService;
this.fhirMedicationAdministrationDao = fhirMedicationAdministrationDao;
this.medicationAdministrationToSlotStatusTranslator=medicationAdministrationToSlotStatusTranslator;
}

private org.hl7.fhir.r4.model.MedicationAdministration createMedicationAdministration(MedicationAdministrationRequest medicationAdministrationRequest) {
Expand All @@ -68,17 +72,15 @@ public org.hl7.fhir.r4.model.MedicationAdministration saveScheduledMedicationAdm
} else {
if (slot.getMedicationAdministration() != null) {
return fhirMedicationAdministrationService.get(slot.getMedicationAdministration().getUuid());
} else if (!StringUtils.isBlank(medicationAdministrationRequest.getUuid())) {
}
if (!StringUtils.isBlank(medicationAdministrationRequest.getUuid())) {
return fhirMedicationAdministrationService.get(medicationAdministrationRequest.getUuid());
} else {
org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest);
if (medicationAdministration.getStatus().equals(org.hl7.fhir.r4.model.MedicationAdministration.MedicationAdministrationStatus.COMPLETED)) {
slot.setStatus(Slot.SlotStatus.COMPLETED);
}
slot.setMedicationAdministration((MedicationAdministration) fhirMedicationAdministrationDao.get(medicationAdministration.getId()));
slotService.saveSlot(slot);
return medicationAdministration;
}
org.hl7.fhir.r4.model.MedicationAdministration medicationAdministration = createMedicationAdministration(medicationAdministrationRequest);
slot.setStatus(medicationAdministrationToSlotStatusTranslator.toSlotStatus(medicationAdministration.getStatus()));
slot.setMedicationAdministration((MedicationAdministration) fhirMedicationAdministrationDao.get(medicationAdministration.getId()));
slotService.saveSlot(slot);
return medicationAdministration;
}
}

Expand Down
Loading

0 comments on commit 28efc13

Please sign in to comment.