Understanding how to implement patient queuing in Bahmni

The use case is a central reception point dealing with the arrival of inpatients and outpatients. Taking the example of outpatients these will generally be for family planning, antenatal or postnatal examination and will be directed to a outpatient clinic common waiting area.

The central reception will determine which form of examination a patient requires and assign an appropriate visit type - fp, antenatal etc

My goal is that the outpatient clinic will be able to see a queue of out patients in total or by visit type ordered by arrival time.

My understanding is that it is possible to establish tabs on the clinical dashboard that show such queues by location.

However for my use case it would seem I need to define queues by visit type or in turn relate location to visit type.

I would welcome advice on how best to model by use case.

Hi @mafrica,

We have a similar Queue configured in Bahmni Default config. You can use the same.

Please let us know if you need more help.

Thank you for the rapid response. This code is in fact in the vagrant box distro, Here is the ful extension.json: { “observations”: { “id”: “bahmni.clinical.consultation.observations”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Observations”, “translationKey”:“OBSERVATIONS_BOARD_LABEL_KEY”, “url”: “concept-set-group/observations”, “default”: true, “icon”: “fa-user-md”, “order”: 1, “requiredPrivilege”: “app:clinical:observationTab” }, “diagnosis”: { “id”: “bahmni.clinical.consultation.diagnosis”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Diagnosis”, “translationKey”:“DIAGNOSIS_BOARD_LABEL_KEY”, “url”: “diagnosis”, “icon”: “fa-user-md”, “order”: 2, “requiredPrivilege”: “app:clinical:diagnosisTab” }, “disposition”: { “id”: “bahmni.clinical.consultation.disposition”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Disposition”, “translationKey”:“DISPOSITION_BOARD_LABEL_KEY”, “url”: “disposition”, “icon”: “fa-user-md”, “order”: 3, “requiredPrivilege”: “app:clinical:dispositionTab” }, “consultationSummary”: { “id”: “bahmni.clinical.consultation.summary”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Consultation”, “translationKey”:“CONSULTATION_BOARD_LABEL_KEY”, “url”: “consultation”, “icon”: “fa-user-md”, “order”: 5, “requiredPrivilege”: “app:clinical:consultationTab” }, “bahmniClinicalOrdersPending”: { “id”: “bahmni.clinical.orders.pending”, “extensionPointId”: “org.bahmni.clinical.orders”, “type”: “link”, “label”: “Pending Orders”, “url”: “pendingOrders”, “icon”: “fa-user-md”, “order”: 5, “requiredPrivilege”: “app:radiologyOrders” }, “bahmniClinicalPatientsSearchAllActivePatients”: { “id”: “bahmni.clinical.patients.search.allActivePatients”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “searchHandler”: “emrapi.sqlSearch.activePatients”, “translationKey”: “MODULE_LABEL_ACTIVE_KEY”, “forwardUrl”: “#/default/patient/{{patientUuid}}/dashboard” }, “label”: “Active”, “order”: 1, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalPatientsSearchActivePatientsForPrograms”: { “id”: “bahmni.clinical.patients.search.activePatients”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “searchHandler”: “emrapi.sqlSearch.activePatients”, “translationKey”: “MODULE_LABEL_PROGRAMS_KEY”, “forwardUrl”: “#/default/patient/{{patientUuid}}/consultationContext” }, “label”: “Active”, “order”: 1, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalPatientsASearchActivePatientsByProvider”: { “id”: “bahmni.clinical.patients.search.activePatientsByProvider”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “searchHandler”: “emrapi.sqlSearch.activePatientsByProvider”, “translationKey”: “MODULE_LABEL_MY_PATIENTS_KEY”, “forwardUrl”: “#/default/patient/{{patientUuid}}/dashboard” }, “label”: “Active”, “order”: 2, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalPatientsSearchOPDActivePatientsByProvider”: { “id”: “bahmni.clinical.patients.search.OPDActivePatientsByProvider”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “searchHandler”: “emrapi.sqlSearch.activePatientsByProvider”, “translationKey”: “MODULE_LABEL_OPD_1_KEY”, “forwardUrl”: “#/default/patient/{{patientUuid}}/consultationContext” }, “label”: “OPD-1”, “order”: 3, “requiredPrivilege”: “app:clinical” }, “activePatientsByLocation”: { “id”: “bahmni.clinical.patients.search.activePatientsByLocation”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “searchHandler”: “emrapi.sqlSearch.activePatientsByLocation”, “translationKey”: “MODULE_LABEL_ACTIVE_PATIENTS_BY_LOCATION”, “forwardUrl”: “#/default/patient/{{patientUuid}}/dashboard” }, “label”: “Active”, “order”: 4, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalPatientsSearchAllPatients”: { “id”: “bahmni.clinical.patients.search.allPatients”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “translationKey”: “MODULE_LABEL_ALL_KEY”, “forwardUrl”: “#/default/patient/{{patientUuid}}/dashboard” }, “label”: “All”, “order”: 5, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalConceptSetGroupObservationsHistory”: { “id”: “bahmni.clinical.conceptSetGroup.observations.history”, “extensionPointId”: “org.bahmni.clinical.conceptSetGroup.observations”, “type”: “config”, “extensionParams”: { “conceptName”: “History and Examination”, “default”: true }, “order”: 1, “requiredPrivilege”: “app:clinical:history” }, “bahmniClinicalConceptSetGroupObservationsVitals”: { “id”: “bahmni.clinical.conceptSetGroup.observations.vitals”, “extensionPointId”: “org.bahmni.clinical.conceptSetGroup.observations”, “type”: “config”, “extensionParams”: { “default”: true, “conceptName”: “Vitals” }, “order”: 2, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalConceptSetGroupObservationsSecondVitals”: { “id”: “bahmni.clinical.conceptSetGroup.observations.secondVitals”, “extensionPointId”: “org.bahmni.clinical.conceptSetGroup.observations”, “type”: “config”, “extensionParams”: { “conceptName”: “Second Vitals”, “showIf”: [ “var visitTypes = [];”, “if(visitTypes.length === 0) return true;”, “var visitTypeName = context.visitType ? context.visitType.name : null;”, “return visitTypes.indexOf(visitTypeName) !== -1;” ] }, “order”: 3, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalConceptSetGroupObservationsObstetrics”: { “id”: “bahmni.clinical.conceptSetGroup.observations.obstetrics”, “extensionPointId”: “org.bahmni.clinical.conceptSetGroup.observations”, “type”: “config”, “extensionParams”: { “conceptName”: “Obstetrics” }, “order”: 4, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalConceptSetGroupObservationsGynaecology”: { “id”: “bahmni.clinical.conceptSetGroup.observations.gynaecology”, “extensionPointId”: “org.bahmni.clinical.conceptSetGroup.observations”, “type”: “config”, “extensionParams”: { “conceptName”: “Gynaecology” }, “order”: 5, “requiredPrivilege”: “app:clinical” }, “bahmniClinicalConceptSetGroupObservationsDischargeSummary”: { “id”: “bahmni.clinical.conceptSetGroup.observations.dischargeSummary”, “extensionPointId”: “org.bahmni.clinical.conceptSetGroup.observations”, “type”: “config”, “extensionParams”: { “conceptName”: “Discharge Summary” }, “order”: 6, “requiredPrivilege”: “Discharge Summary” }, “bahmniClinicalBillingTreatment”: { “id”: “bahmni.clinical.billing.treatment”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Medications”, “translationKey”:“MEDICATIONS_BOARD_LABEL_KEY”, “extensionParams”:{ “tabConfigName”: “allMedicationTabConfig” }, “url”: “treatment”, “icon”: “fa-user-md”, “order”: 7, “requiredPrivilege”: “app:clinical:treatmentTab” }, “bahmniClinicalConsultationOrders”: { “id”: “bahmni.clinical.consultation.orders”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Orders”, “translationKey”:“ORDERS_BOARD_LABEL_KEY”, “url”: “orders”, “icon”: “icon-user-md”, “order”: 6, “requiredPrivilege”: “app:clinical:ordersTab” }, “bahmniClinicalConsultationBacteriology”: { “id”: “bahmni.clinical.consultation.bacteriology”, “extensionPointId”: “org.bahmni.clinical.consultation.board”, “type”: “link”, “label”: “Bacteriology”, “translationKey”:“BACTERIOLOGY_BOARD_LABEL_KEY”, “url”: “bacteriology”, “icon”: “icon-user-md”, “order”: 7, “requiredPrivilege”: “app:clinical:bacteriologyTab” } }

This image shows the clinical screen after opening a visit (from the reception location) using a new visit type of Family Planning Visit. Note the patient by location is 1 which I assume says that the patient is presently associated with reception. The second image is when I log on from the multi-purpose clinic. Here patients by location shows 0. This is not surprising as I cannot find a way to associate a visit type with a location. The other counts are I assume opd: patients currently in an outpatient visit regardless of location; Active: the sum of inpatients and outpatients; my patients:those associated with my user-id; Programs: I assume would be all patients presently engaged in a visit that are also enrolled in programs, but in fact is a little worrying as the listed patient is not enrolled in any program. The final image confirms that the sole active patient is not enrolled in any program.

So, is it possible to associate a visit type with a location or create clinical search tabs by visit type - if yes I would really welcome the suggested code as I find the sql is pushing my understanding.

On the programs tab - could you correct my understanding or suggest a correction that would achieve what I think it is trying to do.

I seem to have cracked this after soon reading and experimentation. The process is essentially 4 step:

  1. Create a global variable (under openmrs advanced settings) for each the search necessary to select the queue members. My queues are for visit type eg family planning consultation for which I have created the variable emrapi.sqlSearch.familyplanning
  2. Give the variable a value comprising a sql search for the required items. I am selecting by visit type in my case an FP visit is type 12, this is a slight adaption of an existing search: select distinct concat(pn.given_name," “, pn.family_name) as name, pi.identifier as identifier, concat(”",p.uuid) as uuid, concat("",v.uuid) as activeVisitUuid, IF(va.value_reference = “Admitted”, “true”, “false”) as hasBeenAdmitted from visit v join person_name pn on v.patient_id = pn.person_id and pn.voided = 0 and v.voided=0 join patient_identifier pi on v.patient_id = pi.patient_id and pi.voided=0 join patient_identifier_type pit on pi.identifier_type = pit.patient_identifier_type_id join global_property gp on gp.property=“emr.primaryIdentifierType” and gp.property_value=pit.uuid join person p on p.person_id = v.patient_id and p.voided=0 join encounter en on en.visit_id = v.visit_id and en.voided=0 join encounter_provider ep on ep.encounter_id = en.encounter_id and ep.voided=0 join provider pr on ep.provider_id=pr.provider_id and pr.retired=0 join person per on pr.person_id=per.person_id and per.voided=0 join location l on l.uuid=${visit_location_uuid} and l.location_id = v.location_id left outer join visit_attribute va on va.visit_id = v.visit_id and va.voided = 0 and va.attribute_type_id = ( select visit_attribute_type_id from visit_attribute_type where name=“Admission Status” ) where v.date_stopped is null and v.visit_type_id=12 order by en.encounter_datetime desc
  3. Add a translation key to openmrs/i18n/clinical/locale_en.json eg
    “MODULE_LABEL_FP”: “Family Planning”, 4 Finally edit openmrs/apps/clinical/extension.json to add code similar to this. The first 2 lines seem to be arbitrary other than I guess it is good for them to be meaningful and unique, the search handler name is from step 1 and the translation key from step 3. Order is tab position and needs to be cognicent of the other tabs:

“bahmniClinicalPatientsSearchFPPatients”: { “id”: “bahmni.clinical.patients.search.FPPatients”, “extensionPointId”: “org.bahmni.patient.search”, “type”: “config”, “extensionParams”: { “searchHandler”: “emrapi.sqlSearch.familyplanning”, “translationKey”: “MODULE_LABEL_FP”, “forwardUrl”: “#/default/patient/{{patientUuid}}/dashboard” }, “label”: “Family Planning”, “order”: 4, “requiredPrivilege”: “app:clinical” },