Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to accomodate Drugchart view where we need to intended and actual administered time #11

Merged
merged 4 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading