Skip to content

Commit

Permalink
EA-198: Add support for configuring Mother Child relationships within…
Browse files Browse the repository at this point in the history
… the EMR API module
  • Loading branch information
mogoodrich committed Aug 6, 2024
1 parent 76327e3 commit 26e9ff6
Show file tree
Hide file tree
Showing 8 changed files with 572 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@

import java.util.List;

import org.openmrs.Location;
import org.openmrs.Patient;
import org.openmrs.api.OpenmrsService;

public interface MaternalService extends OpenmrsService {

/**
* Returns all "newborns" of the specified patient, where "newborn" is defined as a patient who is:
* Returns all "newborns" of the specified patients, where "newborn" is defined as a patient who is:
* - linked to the specified patient by a relationship of type emrapi.motherChildRelationshipType
* - has as an active visit (at the visitLocation, if specified)
* - has as an active visit at the same visit location of the mother
* - has a birthdate that is on or after the start date of the mother's active visit (at the visitLocation, if specified) (note matches on date, not datetime to account for retrospective data entry or only have a date component of birthdate)
*
* @param mother
* @param visitLocation if not null, restrict matching visits to only those at the specified location
* @param mothers
* @return
*/
public List<Newborn> getNewbornsByMother(Patient mother, Location visitLocation);
public List<Newborn> getNewbornsByMother(List<Patient> mothers);

/**
* Returns all mothers of the specified patients(), where "mother" is defined as a patient who is:
* - linked to the specified patient by a relationship of typ emrapi.motherChildRelationshipType
* - has an active visit at the same visit location of the newborn
*
* @param newborns (assumption: these are newborns, method does *not* confirm this)
* @return
*/
public List<Mother> getMothersByNewborn(List<Patient> newborns);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.openmrs.Location;
import org.openmrs.Patient;
Expand All @@ -12,12 +13,17 @@
import org.openmrs.api.APIException;
import org.openmrs.api.impl.BaseOpenmrsService;
import org.openmrs.module.emrapi.EmrApiProperties;
import org.openmrs.module.emrapi.adt.AdtService;
import org.openmrs.module.emrapi.adt.InpatientAdmission;
import org.openmrs.module.emrapi.adt.InpatientAdmissionSearchCriteria;
import org.openmrs.module.emrapi.db.EmrApiDAO;

public class MaternalServiceImpl extends BaseOpenmrsService implements MaternalService {

private EmrApiProperties emrApiProperties;

private AdtService adtService;

private EmrApiDAO emrApiDAO;

public void setEmrApiProperties(EmrApiProperties emrApiProperties) {
Expand All @@ -28,35 +34,101 @@ public void setEmrApiDAO(EmrApiDAO emrApiDAO) {
this.emrApiDAO = emrApiDAO;
}

public List<Newborn> getNewbornsByMother(Patient mother, Location visitLocation) {
public void setAdtService(AdtService adtService) {
this.adtService = adtService;
}

public List<Newborn> getNewbornsByMother(List<Patient> mothers) {

RelationshipType motherChildRelationshipType = emrApiProperties.getMotherChildRelationshipType();

if (motherChildRelationshipType == null) {
throw new APIException("Mother-Child relationship type has not been configured");
}

if (mother == null) {
throw new APIException("Mother cannot be null");
if (mothers == null || mothers.isEmpty()) {
throw new APIException("No mothers provided");
}

Map<String, Object> parameters = new HashMap<>();
parameters.put("mother", mother);
parameters.put("mothers", mothers);
parameters.put("motherChildRelationshipType", motherChildRelationshipType);
parameters.put("visitLocation", visitLocation);

List<?> l = emrApiDAO.executeHqlFromResource("hql/newborns_by_mother.hql", parameters, List.class);

List<Newborn> ret = new ArrayList<>();
List<Visit> visits = new ArrayList<>();

for (Object req : l) {
Object[] row = (Object[]) req;
Newborn newborn = new Newborn();
newborn.setNewborn((Patient) row[0]);
newborn.setNewbornVisit((Visit) row[1]);
newborn.setMother((Patient) row[1]);
visits.add((Visit) row[2]);
ret.add(newborn);
}

// now fetch all the admissions for newborns in the result set
InpatientAdmissionSearchCriteria criteria = new InpatientAdmissionSearchCriteria();
criteria.setVisitIds(visits.stream().map(Visit::getId).collect(Collectors.toList()));
List<InpatientAdmission> admissions = adtService.getInpatientAdmissions(criteria);
Map<Patient, InpatientAdmission> admissionsByPatient = new HashMap<>();
if (admissions != null) {
for (InpatientAdmission admission : admissions) {
admissionsByPatient.put(admission.getVisit().getPatient(), admission);
}
}
for (Newborn newborn : ret) {
newborn.setNewbornAdmission(admissionsByPatient.get(newborn.getNewborn()));
}

return ret;
}

public List<Mother> getMothersByNewborn(List<Patient> newborns) {
RelationshipType motherChildRelationshipType = emrApiProperties.getMotherChildRelationshipType();

if (motherChildRelationshipType == null) {
throw new APIException("Mother-Child relationship type has not been configured");
}

if (newborns == null || newborns.isEmpty()) {
throw new APIException("No newborns provided");
}

Map<String, Object> parameters = new HashMap<>();
parameters.put("babies", newborns);
parameters.put("motherChildRelationshipType", motherChildRelationshipType);

List<?> l = emrApiDAO.executeHqlFromResource("hql/mothers_by_newborn.hql", parameters, List.class);

List<Mother> ret = new ArrayList<>();
List<Visit> visits = new ArrayList<>();

for (Object req : l) {
Object[] row = (Object[]) req;
Mother mother = new Mother();
mother.setMother((Patient) row[0]);
mother.setNewborn((Patient) row[1]);
visits.add((Visit) row[2]);
ret.add(mother);
}

// now fetch all the admissions for mothers in the result set
InpatientAdmissionSearchCriteria criteria = new InpatientAdmissionSearchCriteria();
criteria.setVisitIds(visits.stream().map(Visit::getId).collect(Collectors.toList()));
List<InpatientAdmission> admissions = adtService.getInpatientAdmissions(criteria);
Map<Patient, InpatientAdmission> admissionsByPatient = new HashMap<>();
if (admissions != null) {
for (InpatientAdmission admission : admissions) {
admissionsByPatient.put(admission.getVisit().getPatient(), admission);
}
}
for (Mother mother : ret) {
mother.setMotherAdmission(admissionsByPatient.get(mother.getMother()));
}


return ret;
}
}
13 changes: 13 additions & 0 deletions api/src/main/java/org/openmrs/module/emrapi/maternal/Mother.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.openmrs.module.emrapi.maternal;

import lombok.Data;
import org.openmrs.Patient;
import org.openmrs.module.emrapi.adt.InpatientAdmission;


@Data
public class Mother {
private Patient mother;
private Patient newborn;
private InpatientAdmission motherAdmission;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import lombok.Data;
import org.openmrs.Patient;
import org.openmrs.Visit;
import org.openmrs.module.emrapi.adt.InpatientAdmission;

@Data
public class Newborn {
private Patient newborn;
private Visit newbornVisit;
private Patient mother;
private InpatientAdmission newbornAdmission;
}
18 changes: 18 additions & 0 deletions api/src/main/resources/hql/mothers_by_newborn.hql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
select
mother,
baby,
motherVisit
from
Relationship as motherChildRelationship, Visit as motherVisit, Visit as babyVisit
inner join motherChildRelationship.personA as mother
inner join motherChildRelationship.personB as baby
where
baby in (:babies)
and motherChildRelationship.relationshipType = :motherChildRelationshipType
and motherVisit.patient = mother and motherVisit.stopDatetime is null
and babyVisit.patient = baby and babyVisit.stopDatetime is null
and babyVisit.location = motherVisit.location
and mother.voided = false and baby.voided = false and motherChildRelationship.voided = false and motherVisit.voided = false and babyVisit.voided = false



15 changes: 6 additions & 9 deletions api/src/main/resources/hql/newborns_by_mother.hql
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
select
baby,
mother,
babyVisit
from
Person as mother,
Person as baby,
Relationship as motherChildRelationship,
Visit as motherVisit,
Visit as babyVisit
Relationship as motherChildRelationship, Visit as motherVisit, Visit as babyVisit
inner join motherChildRelationship.personA as mother
inner join motherChildRelationship.personB as baby
where
mother = :mother
and motherChildRelationship.personA = mother
and motherChildRelationship.personB = baby
mother in (:mothers)
and motherChildRelationship.relationshipType = :motherChildRelationshipType
and motherVisit.patient = mother and motherVisit.stopDatetime is null
and babyVisit.patient = baby and babyVisit.stopDatetime is null
and babyVisit.location = motherVisit.location
and year(baby.birthdate) >= year(motherVisit.startDatetime)
and month(baby.birthdate) >= month(motherVisit.startDatetime)
and day(baby.birthdate) >= day(motherVisit.startDatetime)
and (:visitLocation is null or (motherVisit.location = :visitLocation and babyVisit.location = :visitLocation))
and mother.voided = false and baby.voided = false and motherChildRelationship.voided = false and motherVisit.voided = false and babyVisit.voided = false


Expand Down
1 change: 1 addition & 0 deletions api/src/main/resources/moduleApplicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
</property>
<property name="target">
<bean class="org.openmrs.module.emrapi.maternal.MaternalServiceImpl">
<property name="adtService" ref="adtService"/>
<property name="emrApiProperties" ref="emrApiProperties"/>
<property name="emrApiDAO" ref="emrApiDAOImpl"/>
</bean>
Expand Down
Loading

0 comments on commit 26e9ff6

Please sign in to comment.