Skip to content

Commit

Permalink
Back porting to 1.9.x: Encounter autocomplete should filter results by
Browse files Browse the repository at this point in the history
patient - TRUNK-3231
  • Loading branch information
dkayiwa committed Feb 18, 2013
1 parent 0df51b4 commit 8d39599
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 31 deletions.
26 changes: 26 additions & 0 deletions api/src/main/java/org/openmrs/api/EncounterService.java
Expand Up @@ -651,6 +651,32 @@ public List<Encounter> getEncounters(Patient who, Location loc, Date fromDate, D
public List<Encounter> getEncounters(String query, Integer start, Integer length, boolean includeVoided)
throws APIException;

/**
* Searches for encounters by patient id, provider identifier, location, encounter type,
* provider, form or provider name. It returns a specific number of them from the specified
* starting position. If start and length are not specified, then all matches are returned
*
* @param query provider identifier, location, encounter type, provider, form or provider name
* @param patientId the patient id
* @param start beginning index for the batch
* @param length number of encounters to return in the batch
* @param includeVoided Specifies whether voided encounters should be included
* @return list of encounters for the given patient based on batch settings
* @throws APIException
* @since 1.10
* @should fetch encounters by patient id
* @should include voided encounters if includeVoided is set to true
* @should should match on provider identifier
* @should match on the provider name
* @should match on the location name
* @should match on the provider person name
* @should match on the encounter type name
* @should match on the form name
*/
@Authorized( { PrivilegeConstants.VIEW_ENCOUNTERS })
public List<Encounter> getEncounters(String query, Integer patientId, Integer start, Integer length,
boolean includeVoided) throws APIException;

/**
* Get all encounters for a cohort of patients
*
Expand Down
6 changes: 4 additions & 2 deletions api/src/main/java/org/openmrs/api/db/EncounterDAO.java
Expand Up @@ -158,13 +158,14 @@ public List<Encounter> getEncounters(Patient patient, Location location, Date fr
* Get a list of {@link Encounter} by Patient name or identifier based on batch settings
*
* @param query patient name or identifier
* @param patientId the patient id
* @param start beginning index for the batch
* @param length number of encounters to return in the batch
* @param includeVoided Specifies whether voided encounters should be included
* @return list of {@link Encounter} based on batch settings
* @see EncounterService#getEncounters(String, Integer, Integer, boolean)
*/
List<Encounter> getEncounters(String query, Integer start, Integer length, boolean includeVoided);
List<Encounter> getEncounters(String query, Integer patientId, Integer start, Integer length, boolean includeVoided);

/**
* Gets the location of the encounter
Expand All @@ -183,11 +184,12 @@ public List<Encounter> getEncounters(Patient patient, Location location, Date fr
* Return the number of encounters matching a patient name or patient identifier
*
* @param query patient name or identifier
* @param patientId the patient id
* @param includeVoided Specifies whether voided encounters should be included
* @return the number of encounters matching the given search phrase
* @see {@link EncounterService#getCountOfEncounters(String, boolean)}
*/
public Long getCountOfEncounters(String query, boolean includeVoided);
public Long getCountOfEncounters(String query, Integer patientId, boolean includeVoided);

/**
* @see EncounterService#getEncountersByVisit(Visit, boolean)
Expand Down
Expand Up @@ -28,6 +28,7 @@
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
Expand Down Expand Up @@ -244,15 +245,17 @@ public EncounterType getEncounterTypeByUuid(String uuid) {
}

/**
* @see org.openmrs.api.db.EncounterDAO#getEncounters(String, Integer, Integer, boolean)
* @see org.openmrs.api.db.EncounterDAO#getEncounters(String, Integer, Integer, Integer,
* boolean)
*/
@SuppressWarnings("unchecked")
public List<Encounter> getEncounters(String query, Integer start, Integer length, boolean includeVoided) {
if (StringUtils.isBlank(query)) {
public List<Encounter> getEncounters(String query, Integer patientId, Integer start, Integer length,
boolean includeVoided) {
if (StringUtils.isBlank(query) && patientId == null) {
return Collections.emptyList();
}

Criteria criteria = createEncounterByQueryCriteria(query, includeVoided, true);
Criteria criteria = createEncounterByQueryCriteria(query, patientId, includeVoided, true);

if (start != null)
criteria.setFirstResult(start);
Expand Down Expand Up @@ -321,11 +324,12 @@ private Criteria createEncounterCriteria(Cohort patients) {
}

/**
* @see org.openmrs.api.db.EncounterDAO#getCountOfEncounters(java.lang.String, boolean)
* @see org.openmrs.api.db.EncounterDAO#getCountOfEncounters(java.lang.String,
* java.lang.Integer, boolean)
*/
@Override
public Long getCountOfEncounters(String query, boolean includeVoided) {
Criteria criteria = createEncounterByQueryCriteria(query, includeVoided, false);
public Long getCountOfEncounters(String query, Integer patientId, boolean includeVoided) {
Criteria criteria = createEncounterByQueryCriteria(query, patientId, includeVoided, false);

criteria.setProjection(Projections.countDistinct("enc.encounterId"));
return (Long) criteria.uniqueResult();
Expand All @@ -336,26 +340,78 @@ public Long getCountOfEncounters(String query, boolean includeVoided) {
* specified search phrase
*
* @param query patient name or identifier
* @param patientId the patient id
* @param includeVoided Specifies whether voided encounters should be included
* @param orderByNames specifies whether the encounters should be ordered by person names
* @return Criteria
*/
private Criteria createEncounterByQueryCriteria(String query, boolean includeVoided, boolean orderByNames) {
private Criteria createEncounterByQueryCriteria(String query, Integer patientId, boolean includeVoided,
boolean orderByNames) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Encounter.class, "enc");
if (!includeVoided)
criteria.add(Restrictions.eq("voided", false));

criteria = criteria.createCriteria("patient", "pat");
String name = null;
String identifier = null;
if (query.matches(".*\\d+.*")) {
identifier = query;
criteria.add(Restrictions.eq("enc.voided", false));

if (patientId != null) {
criteria.add(Restrictions.eq("enc.patientId", patientId));
if (StringUtils.isNotBlank(query)) {
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
//match on location.name, encounterType.name, form.name
//provider.name, provider.identifier, provider.person.names
MatchMode mode = MatchMode.ANYWHERE;
criteria.createAlias("enc.location", "loc");
criteria.createAlias("enc.encounterType", "encType");
criteria.createAlias("enc.form", "form");
criteria.createAlias("enc.encounterProviders", "enc_prov");
criteria.createAlias("enc_prov.provider", "prov");
criteria.createAlias("prov.person", "person", Criteria.LEFT_JOIN);
criteria.createAlias("person.names", "personName", Criteria.LEFT_JOIN);

Disjunction or = Restrictions.disjunction();
or.add(Restrictions.ilike("loc.name", query, mode));
or.add(Restrictions.ilike("encType.name", query, mode));
or.add(Restrictions.ilike("form.name", query, mode));
or.add(Restrictions.ilike("prov.name", query, mode));
or.add(Restrictions.ilike("prov.identifier", query, mode));

String[] splitNames = query.split(" ");
Disjunction nameOr = Restrictions.disjunction();
for (String splitName : splitNames) {
nameOr.add(Restrictions.ilike("personName.givenName", splitName, mode));
nameOr.add(Restrictions.ilike("personName.middleName", splitName, mode));
nameOr.add(Restrictions.ilike("personName.familyName", splitName, mode));
nameOr.add(Restrictions.ilike("personName.familyName2", splitName, mode));
}
//OUTPUT for provider criteria:
//prov.name like '%query%' OR prov.identifier like '%query%'
//OR ( personName.voided = false
// AND ( personName.givenName like '%query%'
// OR personName.middleName like '%query%'
// OR personName.familyName like '%query%'
// OR personName.familyName2 like '%query%'
// )
// )
Conjunction personNameConjuction = Restrictions.conjunction();
personNameConjuction.add(Restrictions.eq("personName.voided", false));
personNameConjuction.add(nameOr);

or.add(personNameConjuction);

criteria.add(or);
}
} else {
// there is no number in the string, search on name
name = query;
criteria = criteria.createCriteria("patient", "pat");
String name = null;
String identifier = null;
if (query.matches(".*\\d+.*")) {
identifier = query;
} else {
// there is no number in the string, search on name
name = query;
}
criteria = new PatientSearchCriteria(sessionFactory, criteria).prepareCriteria(name, identifier,
new ArrayList<PatientIdentifierType>(), false, orderByNames);
}
criteria = new PatientSearchCriteria(sessionFactory, criteria).prepareCriteria(name, identifier,
new ArrayList<PatientIdentifierType>(), false, orderByNames);

return criteria;
}

Expand Down
20 changes: 15 additions & 5 deletions api/src/main/java/org/openmrs/api/impl/EncounterServiceImpl.java
Expand Up @@ -48,8 +48,7 @@
import org.openmrs.util.OpenmrsConstants;
import org.openmrs.util.OpenmrsUtil;
import org.openmrs.util.PrivilegeConstants;
import org.openmrs.validator.EncounterValidator;
import org.openmrs.validator.ValidateUtil;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;

Expand Down Expand Up @@ -83,7 +82,7 @@ public List<Encounter> getEncountersByPatient(String query, boolean includeVoide
if (query == null)
throw new IllegalArgumentException("The 'query' parameter is required and cannot be null");

return dao.getEncounters(query, null, null, includeVoided);
return dao.getEncounters(query, null, null, null, includeVoided);
}

/**
Expand Down Expand Up @@ -628,15 +627,26 @@ public Map<Integer, List<Encounter>> getAllEncounters(Cohort patients) {
@Override
public List<Encounter> getEncounters(String query, Integer start, Integer length, boolean includeVoided)
throws APIException {
return dao.getEncounters(query, start, length, includeVoided);
return dao.getEncounters(query, null, start, length, includeVoided);
}

/**
* @see org.openmrs.api.EncounterService#getEncounters(java.lang.String, java.lang.Integer,
* java.lang.Integer, java.lang.Integer, boolean)
*/
@Override
@Transactional(readOnly = true)
public List<Encounter> getEncounters(String query, Integer patientId, Integer start, Integer length,
boolean includeVoided) throws APIException {
return dao.getEncounters(query, patientId, start, length, includeVoided);
}

/**
* @see org.openmrs.api.EncounterService#getCountOfEncounters(java.lang.String, boolean)
*/
@Override
public Integer getCountOfEncounters(String query, boolean includeVoided) {
return OpenmrsUtil.convertToInteger(dao.getCountOfEncounters(query, includeVoided));
return OpenmrsUtil.convertToInteger(dao.getCountOfEncounters(query, null, includeVoided));
}

/**
Expand Down
25 changes: 23 additions & 2 deletions web/src/main/java/org/openmrs/web/dwr/DWREncounterService.java
Expand Up @@ -61,6 +61,27 @@ public Vector findEncounters(String phrase, boolean includeVoided) throws APIExc
*/
public Vector findBatchOfEncounters(String phrase, boolean includeVoided, Integer start, Integer length)
throws APIException {
return findBatchOfEncounters(phrase, null, includeVoided, null, null);
}

/**
* Returns a list of matching encounters (depending on values of start and length parameters) if
* the length parameter is not specified, then all matches will be returned from the start index
* if specified.
*
* @param phrase encounter id, provider identifier, location, encounter type, provider, form or
* provider name
* @param patientId the patient id
* @param includeVoided Specifies if voided encounters should be included or not
* @param start the beginning index
* @param length the number of matching encounters to return
* @return list of the matching encounters
* @throws APIException
* @since 1.10
*/
@SuppressWarnings("rawtypes")
public Vector findBatchOfEncounters(String phrase, Integer patientId, boolean includeVoided, Integer start,
Integer length) throws APIException {

// List to return
// Object type gives ability to return error strings
Expand All @@ -79,7 +100,7 @@ public Vector findBatchOfEncounters(String phrase, boolean includeVoided, Intege
if (phrase.matches("\\d+")) {
// user searched on a number. Insert concept with corresponding encounterId
Encounter e = es.getEncounter(Integer.valueOf(phrase));
if (e != null) {
if (e != null && (patientId == null || patientId.equals(e.getPatient().getPatientId()))) {
if (!e.isVoided() || includeVoided == true)
encs.add(e);
}
Expand All @@ -88,7 +109,7 @@ public Vector findBatchOfEncounters(String phrase, boolean includeVoided, Intege
if (phrase == null || phrase.equals("")) {
//TODO get all concepts for testing purposes?
} else {
encs.addAll(es.getEncounters(phrase, start, length, includeVoided));
encs.addAll(es.getEncounters(phrase, patientId, start, length, includeVoided));
}

if (encs.size() == 0) {
Expand Down
2 changes: 2 additions & 0 deletions webapp/src/main/webapp/WEB-INF/dwr.xml
Expand Up @@ -280,7 +280,9 @@
DWRConceptService.getConceptReferenceTerm(Integer conceptReferenceTermId);
DWRConceptService.createConceptReferenceTerm(String code, Integer conceptSourceId, String name);
DWREncounterService.findEncounters(String phrase, boolean includeVoided);
DWREncounterService.findEncounters(String phrase, Integer patientId, boolean includeVoided);
DWREncounterService.findBatchOfEncounters(String phrase, boolean includeVoided, Integer start, Integer length);
DWREncounterService.findBatchOfEncounters(String phrase, Integer patientId, boolean includeVoided, Integer start, Integer length);
DWREncounterService.findCountAndEncounters(String phrase, boolean includeVoided, Integer start, Integer length, boolean getMatchCount);
DWREncounterService.findCountAndLocations(String phrase, boolean includeRetired, Integer start, Integer length, boolean getMatchCount);
DWREncounterService.findBatchOfLocations(String searchValue, boolean includeRetired, Integer start, Integer length);
Expand Down
1 change: 1 addition & 0 deletions webapp/src/main/webapp/WEB-INF/messages.properties
Expand Up @@ -2405,6 +2405,7 @@ Visit.clickToViewEncounters=Click to view encounters
Visit.clickToHideEncounters=Click to hide encounters
Visit.noVisitAssigned=No visit assigned
Visit.cannotPurgeVisitWithEncounters=Can't purge a visit that has encounters associated to it
Visit.encounter.search.placeholder=Enter encounter id, provider identifier, location, form, encounter type or provider name

Visit.configure.startCloseVisitsTask=Start auto close visits task
Visit.configure.closeVisitsTask.failedToStart=Failed to start task
Expand Down
Expand Up @@ -41,11 +41,11 @@ function addEncounter() {
row.parentNode.insertBefore(newrow, row);
numberOfClonedElements++;
// set up the autocomplete for selecting encounters to add
new AutoComplete('visitEncounters[' + index + ']-display', new CreateCallback({maxresults:100}).encounterCallback(), {
new AutoComplete('visitEncounters[' + index + ']-display', new CreateCallback({maxresults:100, patientId:${param.patientId}}).encounterCallback(), {
select: function(event, ui) {
jquerySelectEscaped('visitEncounters[' + index + ']').val(ui.item.object.encounterId);
},
placeholder:'<openmrs:message code="Encounter.search.placeholder" javaScriptEscape="true"/>'
placeholder:'<openmrs:message code="Visit.encounter.search.placeholder" javaScriptEscape="true"/>'
});
}
Expand Down
Expand Up @@ -131,7 +131,7 @@ function CreateCallback(options) {

// do NOT return false if no text given, instead should return all answers
thisObject.searchCounter += 1;
DWREncounterService.findEncounters(q, false, thisObject.makeRows(q, response, thisObject.searchCounter, thisObject.displayEncounter));
DWREncounterService.findBatchOfEncounters(q, options.patientId, false, null, maxresults, thisObject.makeRows(q, response, thisObject.searchCounter, thisObject.displayEncounter));
}}

/**
Expand Down

0 comments on commit 8d39599

Please sign in to comment.