Skip to content

Buendia and OpenMRS

Ka-Ping Yee edited this page Jun 20, 2019 · 7 revisions
2019 status: Current (but incomplete)

These are the kinds of information we store in OpenMRS, together with the relevant service interfaces and model classes in the OpenMRS API that we use:

  1. Clinicians, to identify who made observations or gave orders:
    • ProviderService (Provider)
  2. Personal details of patients:
    • PersonService (Person, PersonName, PersonAttribute)
    • PatientService (Patient, PatientIdentifier)
  3. Rooms or buildings where patients are placed:
    • LocationService (Location)
  4. Medical observations, such as vital signs and symptoms:
    • EncounterService (Encounter, Obs)
  5. Concepts, which represent the observed information:
    • ConceptService (Concept, ConceptName)
  6. Orders, such as treatments, medications, tests, or other procedures:
    • OrderService (Order)
  7. Forms, for entering observations and customizing the UI:
    • FormService (Form, Field, FormField)

There is much more to these services, but we primarily use just these parts, and also simplify and consolidate them to some extent to keep the user experience clean and easy.

1. Clinicians

The tablet app is designed to be used by all people involved in providing medical care to patients ("clinicians" is a convenient shorthand for "doctors and nurses", though the user audience might also include other people who carry out procedures such as lab technicians or sanitation staff). In the app's user interface and source code, these are called "users".

In OpenMRS, the Provider class is what represents these people (think of "care provider"). Our "users" are OpenMRS "providers"; the users table in the app corresponds to Provider models accessed through the ProviderService.

OpenMRS also has a UserService and a User model class, which represent the accounts (with usernames and passwords) that are used to log in to the OpenMRS web UI and to authenticate requests to OpenMRS REST APIs. These accounts are not related to our app's users. Because all our users log in without passwords, it doesn't make sense for each of them to have their own OpenMRS username and password. Instead we have just a single OpenMRS User, with one username and one password, used for all API requests by all tablets. The username and password are configured in the app's settings, so that a set of tablets can be prepared and deployed in a state such that they are immediately ready to use.

During the ebola response, we decided that the convenience and speed of one-click login (just tap your initials) outweighed the security benefits of passwords, and in our threat model the tablets were interchangeable (tablets move arbitrarily around the facility, and anybody can grab any tablet), so security was based on physical control of the tablets themselves. In future, changes to these assumptions and security priorities might lead to using a separate OpenMRS User for each clinician, though that's only one of several possible ways to implement per-clinician passwords.

2. Patients

The OpenMRS Person class is used to represent personal details of both patients and clinicians. The Patient class just extends this a bit by adding a patient identifier.

Only a few basic properties reside in the Person class itself, such as birthdate and gender. Names are conveyed in PersonName objects because OpenMRS allows each person to have an unlimited number of names, one of which is marked as "preferred". All other aspects of personal details are stored using instances of PersonAttribute, which is a generalized way of storing anything about a person — you can define arbitrary properties using PersonAttributeType. For example, you could create a PersonAttributeType that means "favourite colour" and then a PersonAttribute that indicates that a particular patient's favourite colour is green. In other words, each Person can have extra information represented in key-value pairs with a PersonAttributeType as the key and a PersonAttribute as the value.

Each patient can have an arbitrary number of identifiers, as well, to accommodate the possibility of patient records moving between or being linked to various electronic systems. Similarly, you define a PatientIdentifierType and then add a PatientIdentifier to the patient specifying a PatientIdentifierType and the patient's identifier (a string) in that ID system.

3. Locations

OpenMRS locations can have other locations as their parents, so locations can be arranged in an arbitrary tree hierarchy. However, to keep things simpler and easier to configure, Buendia assumes that there are exactly two levels in the tree. For an Ebola center this represents tents within zones; in a hospital setting it could represent rooms within wards. The top level typically corresponds to some kind of difference in the type of care that a patient is getting (e.g. in the ICU or not).

4. Observations

In OpenMRS, all observations must take place within an Encounter, which is a record of a specific time and place that a particular clinician met with a particular patient. It is assumed that only during such an encounter can a clinician observe symptoms, take measurements, ask questions of the patient, and so on. OpenMRS will not let you store the fact that a patient has a temperature of 38.5°C unless you first create an encounter, specify the provider and location, indicate the type of encounter from a predetermined set, then within the encounter create an observation with "temperature in degrees Celsius" as the concept and 38.5 as the numeric value.

Buendia largely hides encounters, instead focusing on observations.

5. Concepts

6. Orders

7. Forms

Buendia uses OpenMRS forms to define data entry forms for entering observations. The Buendia app supports just 5 types of questions corresponding to 5 data types:

  • Numeric: type a number into a text field
  • Text: type text into a large text field (for long-form prose and notes)
  • Select one: tap one of a set of buttons showing the available choices
  • Select multiple: toggle on any number of buttons in a group of buttons showing the available choices
  • Yes or no: given "Yes" and "No" buttons, tap one

Charts

Clone this wiki locally