diff --git a/api/pom.xml b/api/pom.xml index 7dfdbee..f119a5e 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -111,6 +111,11 @@ lombok provided + + org.openmrs.module + bedmanagement-api + provided + org.openmrs.web openmrs-web diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java new file mode 100644 index 0000000..aaa297f --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/WardDAO.java @@ -0,0 +1,15 @@ +package org.openmrs.module.ipd.api.dao; + +import org.openmrs.Location; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + +import java.util.List; + +public interface WardDAO { + + List getAdmittedPatients(Location location); + + WardPatientsSummary getWardPatientSummary(Location location); + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java new file mode 100644 index 0000000..44e3c27 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAO.java @@ -0,0 +1,76 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.openmrs.Location; +import org.openmrs.module.ipd.api.dao.WardDAO; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import org.hibernate.query.Query; + +import java.util.ArrayList; +import java.util.List; + +@Repository +public class HibernateWardDAO implements WardDAO { + + private static final Logger log = LoggerFactory.getLogger(HibernateWardDAO.class); + + private final SessionFactory sessionFactory; + + @Autowired + public HibernateWardDAO(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + public List getAdmittedPatients(Location location) { + Session session = this.sessionFactory.getCurrentSession(); + try { + Query query = session.createQuery("select NEW org.openmrs.module.ipd.api.model.AdmittedPatient(assignment," + + "(COUNT(DISTINCT o.orderId) - COUNT (DISTINCT s.order.orderId)))" + + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + + "JOIN org.openmrs.Encounter e on e.visit = v " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l on locmap.location = l " + + "LEFT JOIN org.openmrs.Order o on o.encounter = e " + + "LEFT JOIN Slot s on s.order = o " + + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location " + + "GROUP BY assignment.patient, v " + + "ORDER BY assignment.startDatetime desc"); + + query.setParameter("location", location); + return query.getResultList(); + } + catch (Exception ex){ + log.error("Exception at WardDAO getAdmittedPatients ",ex.getStackTrace()); + } + return new ArrayList<>(); + } + + @Override + public WardPatientsSummary getWardPatientSummary(Location location) { + Session session = this.sessionFactory.getCurrentSession(); + try { + Query query = session.createQuery( + "select NEW org.openmrs.module.ipd.api.model.WardPatientsSummary(COUNT(assignment)) " + + "from org.openmrs.module.bedmanagement.entity.BedPatientAssignment assignment " + + "JOIN org.openmrs.module.bedmanagement.entity.BedLocationMapping locmap on locmap.bed = assignment.bed " + + "JOIN org.openmrs.Location l on locmap.location = l " + + "JOIN org.openmrs.Visit v on v.patient = assignment.patient " + + "where assignment.endDatetime is null and v.stopDatetime is null and l.parentLocation = :location"); + query.setParameter("location", location); + return (WardPatientsSummary) query.getSingleResult(); + } catch (Exception e) { + log.error("Exception at WardDAO getAdmittedPatients ",e.getStackTrace()); + } + return new WardPatientsSummary(); + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java new file mode 100644 index 0000000..760d461 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/AdmittedPatient.java @@ -0,0 +1,30 @@ +package org.openmrs.module.ipd.api.model; + +import org.openmrs.module.bedmanagement.entity.BedPatientAssignment; + +public class AdmittedPatient extends BedPatientAssignment { + + private Long newTreatments; + + public AdmittedPatient(BedPatientAssignment bedPatientAssignment, Long newTreatments){ + super.setId(bedPatientAssignment.getId()); + super.setBed(bedPatientAssignment.getBed()); + super.setPatient(bedPatientAssignment.getPatient()); + super.setEncounter(bedPatientAssignment.getEncounter()); + super.setStartDatetime(bedPatientAssignment.getStartDatetime()); + super.setEndDatetime(bedPatientAssignment.getEndDatetime()); + super.setUuid(bedPatientAssignment.getUuid()); + super.setVoided(bedPatientAssignment.getVoided()); + super.setVoidReason(bedPatientAssignment.getVoidReason()); + this.newTreatments=newTreatments; + } + + public void setNewTreatments(Long newTreatments) { + this.newTreatments = newTreatments; + } + + public Long getNewTreatments() { + return newTreatments; + } + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java b/api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java new file mode 100644 index 0000000..63f4a52 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/IPDWardPatientDetails.java @@ -0,0 +1,17 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class IPDWardPatientDetails { + + private List activePatients; + private WardPatientsSummary ipdWardWardPatientsSummary; + +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java b/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java new file mode 100644 index 0000000..ccccf6b --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/model/WardPatientsSummary.java @@ -0,0 +1,18 @@ +package org.openmrs.module.ipd.api.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Getter +public class WardPatientsSummary { + private Long totalPatients = 0L; + + // to be added in future +// private Integer myPatients; +// private Integer toBeDischargedPatients; +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java new file mode 100644 index 0000000..c5faff9 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/WardService.java @@ -0,0 +1,12 @@ +package org.openmrs.module.ipd.api.service; + +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + + +public interface WardService { + + WardPatientsSummary getIPDWardPatientSummary(String wardUuid); + + IPDWardPatientDetails getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit); +} diff --git a/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java new file mode 100644 index 0000000..a1d8743 --- /dev/null +++ b/api/src/main/java/org/openmrs/module/ipd/api/service/impl/WardServiceImpl.java @@ -0,0 +1,55 @@ +package org.openmrs.module.ipd.api.service.impl; + +import org.openmrs.Location; +import org.openmrs.api.LocationService; +import org.openmrs.api.context.Context; +import org.openmrs.module.ipd.api.dao.WardDAO; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import org.openmrs.module.ipd.api.service.WardService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@Transactional +public class WardServiceImpl implements WardService { + + private final WardDAO wardDAO; + + @Autowired + public WardServiceImpl(WardDAO wardDAO) { + this.wardDAO = wardDAO; + } + + + @Override + public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { + Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); + return wardDAO.getWardPatientSummary(location); + } + + @Override + public IPDWardPatientDetails getWardPatientsByUuid(String wardUuid, Integer offset, Integer limit) { + Location location= Context.getService(LocationService.class).getLocationByUuid(wardUuid); + List activePatients= wardDAO.getAdmittedPatients(location); + if (activePatients==null){ + return new IPDWardPatientDetails(new ArrayList<>(),new WardPatientsSummary()); + } + offset = Math.min(offset, activePatients.size()); + limit = Math.min(limit, activePatients.size() - offset); + + WardPatientsSummary wardPatientsSummary = computePatientStats(activePatients); + return new IPDWardPatientDetails(activePatients.subList(offset, offset + limit), wardPatientsSummary); + } + + private WardPatientsSummary computePatientStats(List activePatients){ + WardPatientsSummary wardPatientsSummary =new WardPatientsSummary(); + wardPatientsSummary.setTotalPatients(activePatients !=null ? activePatients.size() : 0L); + return wardPatientsSummary; + } +} diff --git a/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java new file mode 100644 index 0000000..58d810e --- /dev/null +++ b/api/src/test/java/org/openmrs/module/ipd/api/dao/impl/HibernateWardDAOIntegrationTest.java @@ -0,0 +1,26 @@ +package org.openmrs.module.ipd.api.dao.impl; + +import org.hibernate.SessionFactory; +import org.junit.Test; +import org.openmrs.module.ipd.api.BaseIntegrationTest; +import org.openmrs.module.ipd.api.dao.WardDAO; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +public class HibernateWardDAOIntegrationTest extends BaseIntegrationTest { + + @Autowired + private WardDAO wardDAO; + + @Autowired + private SessionFactory sessionFactory; + + + @Test + public void shouldGetAdmittedPatients() { + List assignments= wardDAO.getAdmittedPatients(null); + + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java new file mode 100644 index 0000000..d1b927b --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/AdmittedPatientResponse.java @@ -0,0 +1,25 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.openmrs.module.ipd.api.model.AdmittedPatient; +import org.openmrs.module.webservices.rest.web.ConversionUtil; +import org.openmrs.module.webservices.rest.web.representation.Representation; + +@Getter +@Setter +@Builder +public class AdmittedPatientResponse { + + private Object patientDetails; + private Object bedDetails; + private Long newTreatments; + + public static AdmittedPatientResponse createFrom(AdmittedPatient admittedPatient) { + return AdmittedPatientResponse.builder(). + patientDetails(ConversionUtil.convertToRepresentation(admittedPatient.getPatient(), Representation.DEFAULT)). + bedDetails(ConversionUtil.convertToRepresentation(admittedPatient.getBed(),Representation.REF)). + newTreatments(admittedPatient.getNewTreatments()).build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java new file mode 100644 index 0000000..10e8f33 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientDetailsResponse.java @@ -0,0 +1,24 @@ +package org.openmrs.module.ipd.contract; + +import lombok.Builder; +import lombok.Getter; +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; + +import java.util.List; +import java.util.stream.Collectors; + +@Getter +@Builder +public class IPDWardPatientDetailsResponse { + + private List admittedPatients; + private Long totalPatients; + + + public static IPDWardPatientDetailsResponse createFrom(IPDWardPatientDetails ipdWardPatientDetails) { + return IPDWardPatientDetailsResponse.builder(). + admittedPatients(ipdWardPatientDetails.getActivePatients().stream().map(AdmittedPatientResponse::createFrom).collect(Collectors.toList())). + totalPatients(ipdWardPatientDetails.getIpdWardWardPatientsSummary().getTotalPatients()). + build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java new file mode 100644 index 0000000..71c342a --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardPatientSummaryResponse.java @@ -0,0 +1,21 @@ +package org.openmrs.module.ipd.contract; + + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + +@Getter +@Setter +@Builder +public class IPDWardPatientSummaryResponse { + + private Long totalPatients; + + public static IPDWardPatientSummaryResponse createFrom(WardPatientsSummary wardPatientsSummary){ + return IPDWardPatientSummaryResponse.builder(). + totalPatients(wardPatientsSummary.getTotalPatients()). + build(); + } +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java new file mode 100644 index 0000000..e82967e --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/contract/IPDWardResponse.java @@ -0,0 +1,25 @@ +package org.openmrs.module.ipd.contract; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.openmrs.Location; +import org.openmrs.module.bedmanagement.AdmissionLocation; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class IPDWardResponse { + private String uuid; + private String name; + + public static IPDWardResponse createFrom (AdmissionLocation admissionLocation){ + return IPDWardResponse.builder(). + uuid(admissionLocation.getWard().getUuid()). + name(admissionLocation.getWard().getName()). + build(); + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java new file mode 100644 index 0000000..c177e56 --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/controller/IPDWardController.java @@ -0,0 +1,53 @@ +package org.openmrs.module.ipd.controller; + +import lombok.extern.slf4j.Slf4j; +import org.openmrs.module.ipd.api.model.*; +import org.openmrs.module.ipd.contract.*; +import org.openmrs.module.ipd.service.IPDWardService; +import org.openmrs.module.webservices.rest.web.RestConstants; +import org.openmrs.module.webservices.rest.web.RestUtil; +import org.openmrs.module.webservices.rest.web.v1_0.controller.BaseRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.text.ParseException; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + +@Controller +@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/ipd/wards") +@Slf4j +public class IPDWardController extends BaseRestController { + + private IPDWardService ipdWardService; + + @Autowired + public IPDWardController(IPDWardService ipdWardService) { + this.ipdWardService = ipdWardService; + } + + @RequestMapping(value = "{wardUuid}/summary",method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getIPDWardPatientStats (@PathVariable("wardUuid") String wardUuid) throws ParseException { + WardPatientsSummary wardPatientsSummary = ipdWardService.getIPDWardPatientSummary(wardUuid); + return new ResponseEntity<>(IPDWardPatientSummaryResponse.createFrom(wardPatientsSummary), OK); + } + + @RequestMapping(value = "{wardUuid}/patients", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getIPDWardPatient(@PathVariable("wardUuid") String wardUuid, + @RequestParam(value = "offset") Integer offset, + @RequestParam (value = "limit") Integer limit) throws ParseException { + try { + IPDWardPatientDetails wardPatientDetails = ipdWardService.getIPDPatientByWard(wardUuid,offset,limit); + return new ResponseEntity<>(IPDWardPatientDetailsResponse.createFrom(wardPatientDetails), OK); + } catch (Exception e) { + log.error("Runtime error while trying to create new schedule", e); + return new ResponseEntity<>(RestUtil.wrapErrorResponse(e, e.getMessage()), BAD_REQUEST); + } + } + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java new file mode 100644 index 0000000..346307c --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/IPDWardService.java @@ -0,0 +1,13 @@ +package org.openmrs.module.ipd.service; + +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; + +public interface IPDWardService { + + WardPatientsSummary getIPDWardPatientSummary(String wardUuid); + + IPDWardPatientDetails getIPDPatientByWard(String wardUuid,Integer offset,Integer limit); + + +} diff --git a/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java new file mode 100644 index 0000000..2b10a5e --- /dev/null +++ b/omod/src/main/java/org/openmrs/module/ipd/service/impl/IPDWardServiceImpl.java @@ -0,0 +1,33 @@ +package org.openmrs.module.ipd.service.impl; + + +import org.openmrs.module.ipd.api.model.IPDWardPatientDetails; +import org.openmrs.module.ipd.api.model.WardPatientsSummary; +import org.openmrs.module.ipd.api.service.WardService; +import org.openmrs.module.ipd.service.IPDWardService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class IPDWardServiceImpl implements IPDWardService { + + private final WardService wardService; + + @Autowired + public IPDWardServiceImpl(WardService wardService) { + this.wardService = wardService; + } + + + @Override + public WardPatientsSummary getIPDWardPatientSummary(String wardUuid) { + return wardService.getIPDWardPatientSummary(wardUuid); + } + + @Override + public IPDWardPatientDetails getIPDPatientByWard(String wardUuid,Integer offset,Integer limit) { + return wardService.getWardPatientsByUuid(wardUuid,offset,limit); + } +}