Medical (EMR)
Medical Patient
MedicalPatient
s represents patients in a facility. It includes limited information about them that cannot be used to identify them (those are stored in PersonalDetails
)
Searching For Patients
type SearchConfiguration {
text: string // the search string to be used
organization: string // the facility id to use to limit the number of results
}
type SearchConfiguration {
text: string // the search string to be used
organization: string // the facility id to use to limit the number of results
}
For easier search of MedicalPatient
s via their PersonalDetails
, a convinience operator $search
is implemented. it accepts a SearchConfiguration
object that will be used to match the following fields:
name.firstName
(fuzzy match, case insensitive)name.lastName
(fuzzy match, case insensitive)name.firstName and name.lastName
(when searchstring has the characted,
will be used to search combination of both fields with last name first)
Connecting A Patient Account
a MedicalPatient
can be associated to an owner account (aka PatientAccount
) via 2 ways:
- a privileged user updating
MedicalPatient.account
to the uid of anAccount
; or - creating an
AccountInvitation
with typepatient
w/c would send an invitation code to an account that it can use to signup and be automatically linked to a chosenMedicalPatient
Note
An account-invitation can be created using the account-invitations
API's create
method.
Merge Patient Profiles (and records)
2 patient profile (along with their records) can be merged using the merge
patch operator. It will do the following merge strategy:
- merge the
to merge px
' personal details to thetarget px
's personal details (wheretarget px
s takes priority) - mark to
to merge px
's profile (/medical-patients
) as merged to thetarget px
ToMergePx.mergedTo == TargetPx.id
- archive the
to merge px
's profile - re-assign all records of
to merge px
totarget px
; i.e.- all medical records
- all invoices, invoice items, and payments
- diagnostic tests/records
- insurance coverages
- inventory transactions
Example
merge Px1
and Px2
where Px1
(target px
) would be retained, and Px2
(to merge
px) archived (but marked as merged to Px1
)
# merge Px2 to Px1
PATCH /medical-patients/<Px1.id>
{ merge: <Px2.id> }
# merge Px2 to Px1
PATCH /medical-patients/<Px1.id>
{ merge: <Px2.id> }
QR Code
Generates a JWT encoding selected data (set per service) including an access token that can be used to fetch the associated document without loggin in a privileged user.
Encoding
# trigger the operator
GET /medical-patients/randomid?$generateQRCode=true
# responsed with a JWT which is expected to be encoded
# in the fronted to a QR image
ey****.***.***
# trigger the operator
GET /medical-patients/randomid?$generateQRCode=true
# responsed with a JWT which is expected to be encoded
# in the fronted to a QR image
ey****.***.***
Scanning and Parsing
The QR code must be decoded and parsed as a JWT. This JWT contains the ff standard fields (w/c may include additional fields depending on the service)
typ
the type of the JWT which is usually the service where the QR code was generatedsub
id of the document associated to the JWTaccessToken
(optional) access token that can be used to re/query all relevant encoded data in the JWT
const decodedFromQRCode = 'ey***.***.****';
const payload = parsedJWTPayload(decodedFromQRCode);
// { typ: 'medical-patient', sub: 'randomid', accessToken: 'ey****.***.***' }
const requeried = await http.get(`/medical-patients/${payload.sub}`, {
headers: { Authorization: `Bearer ${payload.accessToken}` }
});
// { id: 'randomid', ... }
const decodedFromQRCode = 'ey***.***.****';
const payload = parsedJWTPayload(decodedFromQRCode);
// { typ: 'medical-patient', sub: 'randomid', accessToken: 'ey****.***.***' }
const requeried = await http.get(`/medical-patients/${payload.sub}`, {
headers: { Authorization: `Bearer ${payload.accessToken}` }
});
// { id: 'randomid', ... }
Medical Records
Creating Medical Records
Created Medical Records are drafts
until finalized either via directly finalizing the MedicalRecord
or via the cascading effect of finalizing a MedicalEncounter
.
Finalizing Medical Records
Only when a MedicalRecord
is finailized will history tracking be enabled on a MedicalRecord
so finalizing it is important. There are 2 ways to finalize a MedicalRecord
:
- Finishing a
MedicalEncounter
will finalize allMedicalRecord
s associated to it; or - A special
patch
operatorfinalize: true
can be use in themedical-records
API'spatch
method.
Example
curl <base-url>/medical-records/<medical-record-id> \
-X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>"
-d "{
"finalize": true,
}"
curl <base-url>/medical-records/<medical-record-id> \
-X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>"
-d "{
"finalize": true,
}"
Medical Record Types
Care Plans
A care plan is a type of the MedicalNote record. This record contains the following:
Field | Type | Description |
---|---|---|
type | String | The record type. I.e. care-plan |
order | String | The MedicalProcedureOrder id |
text | String | The field for doctor's notes |
doctor | String | The uid of the doctor who provided the record |
Lab Orders
There are two medical records that comprise the lab test flow: lab-test-order
and lab-test-result
. It should bear mentioning at this point that there are several Diagnostic
entities related to these records. The distinctions are as follows:
LabTestOrder
: When a doctor identifies a need for lab tests, the doctor may produce a written order for the laboratory's reference. This is represented by aLabTestOrder
, which is aMedicalRecord
of typelab-test-order
.DiagnosticTest
: The doctor may write down one or more tests as part of the written order. Digitally, this is represented by aLabTestOrder
containing references to one or moreDiagnosticTest
s.DiagnosticTest
s in this case are a stand-alone entity that contains information about the actual test to be done. For example, a singleLabTestOrder
may include theDiagnosticTest
for Complete Blood Count and theDiagnosticTest
for Urinalysis.DiagnosticMeasure
: A singleDiagnosticTest
may in fact be composed of one or more values that are measured as part of the overall test. These are called test measures, and they are represented by another entity calledDiagnosticMeasure
. A good example here is the Complete Blood Count: it is a singleDiagnosticTest
, but is composed of severalDiagnosticMeasure
s for Red Blood Cell count, White Blood Cell count, Platelet count, Differential count (eosinophils, basophils, etc.), and so on.LabTestResult
: A doctor's order for lab tests is fulfilled by a laboratory that will produce results for each test declared in the order. Each test result will also have values for each test measure declared in the test. To manage this, aLabTestResult
is used, which is aMedicalRecord
of typelab-test-result
. ALabTestResult
represents the results for a singleDiagnosticTest
. It contains an array of result values, one for eachDiagnosticMeasure
associated with thatDiagnosticTest
. SinceLabTestOrder
s can have more than oneDiagnosticTest
, it is expected that it can also have more than oneLabTestResult
.
With these distinctions and flow in mind, the shape of each relevant record can now be understood:
LabTestOrder
Field | Type | Description |
---|---|---|
type | String | Should be 'lab-test-order' |
tests | LabTestOrderItem[] | Array of items, which represent the tests in the order |
LabTestOrderItem
Field | Type | Description |
---|---|---|
id | String | The ID of the DiagnosticTest to be done |
name | String | The name of the DiagnosticTest |
LabTestResult
Field | Type | Description |
---|---|---|
order | String | The ID of the LabTestOrder to which this result is attached |
test | String | The ID of the DiagnosticTest for which this result is given |
results | LabTestResultItem[] | Array of items, which represent each result value in the test |
LabTestResultItem
Field | Type | Description |
---|---|---|
test | String | The ID of the DiagnosticTest, for convenience |
testName | String | The name of the DiagnosticTest, for convenience |
measure | String | The ID of the DiagnosticMeasure for which this result value is given |
measureName | String | The name of the DiagnosticMeasure, for convenience |
value | any | The result value for the DiagnosticMeasure |
sivalue | any | The SI counterpart of value, if both Conventional units and SI units are provided |
values | any[] | In some cases, DiagnosticMeasures require more than one value. Either value or values are filled up |
sivalues | any[] | The SI counterpart of values |
Imaging Orders
Imaging orders follow the same flow as lab orders. In fact, they share most of the same entities. Here are some crucial differences:
ImagingTestOrder
: Same asLabTestOrder
, except this is aMedicalRecord
of typeimaging-test-order
.DiagnosticTest
: Exactly the same use case as for lab. To distinguish the two use cases,DiagnosticTest
s have typelaboratory
if intended forLabTestOrder
s, and typeradiology
if intended forImagingTestOrder
s.DiagnosticMeasure
: Unused in practice. Imaging tests produce images, which do not fall under the same test measure model. Instead, each imagingDiagnosticTest
expects only a single, qualitative, rich-text report as its result.ImagingTestResult
: Same asLabTestResult
, except this is aMedicalRecord
of typeimaging-test-result
. As hinted above, there is only ever a single result: a qualitative rich-text report.
ImagingTestOrder
Field | Type | Description |
---|---|---|
type | String | Should be 'imaging-test-order' |
tests | ImagingTestOrderItem[] | Array of items, which represent the tests in the order |
ImagingTestOrderItem
Field | Type | Description |
---|---|---|
id | String | The ID of the DiagnosticTest to be done |
name | String | The name of the DiagnosticTest |
ImagingTestResult
Field | Type | Description |
---|---|---|
order | String | The ID of the ImagingTestOrder to which this result is attached |
test | String | The ID of the DiagnosticTest for which this result is given |
results | ImagingTestResultItem[] | Array of only a single item: the rich-text report |
ImagingTestResultItem
Field | Type | Description |
---|---|---|
test | String | The ID of the DiagnosticTest, for convenience |
testName | String | The name of the DiagnosticTest, for convenience |
value | any | The rich-text report as an HTML string |
Medical Forms
Medical forms is the generic medical record object for the following certificates.
- Medical Certificate
- Fitness Certificate
- Health History
- Waiver
- Claims
- Questionnaires
- Generic - The generic version for flexible usage
This record has the following fields:
Field | Type | Description |
---|---|---|
type | String | The record type. Enum: med-certificate , fit-certificate , health-history , waiver , claims , questionnaire and general |
order | String | The order id |
template | String | Template id. This record has a dynamic template that represents the layout of the form |
values | Array | The values array of objects contains all of the data to be substituted to form's template layout |
Here's a sample template data:
{
"id": "5cc7f95b2d89a34340b79111",
"type": "med-certificate",
"template": "I, {doctor_name_0}, after careful examination hereby certify that {patient_name_0} who complained about {patient_complaint_0} was suffering from {patient_diagnosis_0}. \n<br>\nI consider that a period of absence from {custom_text_absence_from_0} from {date_0} to {date_1} is absolutely necessary for the restoration of patient's health.",
"name": "Medical Certificate Template 2",
"description": "Template 2. For general purposes (Without Follow-up date)"
}
{
"id": "5cc7f95b2d89a34340b79111",
"type": "med-certificate",
"template": "I, {doctor_name_0}, after careful examination hereby certify that {patient_name_0} who complained about {patient_complaint_0} was suffering from {patient_diagnosis_0}. \n<br>\nI consider that a period of absence from {custom_text_absence_from_0} from {date_0} to {date_1} is absolutely necessary for the restoration of patient's health.",
"name": "Medical Certificate Template 2",
"description": "Template 2. For general purposes (Without Follow-up date)"
}
You'll notice that the template literals contains the keywords enclosed with opening and closing curly braces. These are the tokens to be use for interpolating the data from the values
field.
Prescriptions
A Prescription is a medical record with type medication-order
. This is the digital representation of the patient's medication order that contains a list of medicines. Medicines are populated in the field called items[Medicine]
. The prescription document also contains the following information, clinic info, patient details, and medicines.
Prescription
Field | Type | Description |
---|---|---|
type | String | Medical record type. I.e. medication-order |
note | String | Optional doctor's note |
items | Array | An array of Medicine objects |
Medicine
Field | Type | Description |
---|---|---|
medicine | String | Reference id to the medicine data. |
brandName | String | Brand name of the medicine |
genericName | String | Generic name of the medicine |
dispense | String | Medicine dispense |
dosageSig | String | Medicine dosage signature |
dosageAmount | Number | Amount of dosage |
formulation | String | Medicine formulation |
formulationClassification | String | Medicine formulation classification |
formulationForm | String | Medicine form of formulation |
frequency | String | Medicine intake frequency |
note | String | Optional doctor notes |
QR Code
Generates a JWT encoding selected data (set per service) including an access token that can be used to fetch the associated document without loggin in a privileged user.
Encoding
# trigger the operator
GET /medical-records/randomid?$generateQRCode=true
# responsed with a JWT which is expected to be encoded
# in the fronted to a QR image
ey****.***.***
# trigger the operator
GET /medical-records/randomid?$generateQRCode=true
# responsed with a JWT which is expected to be encoded
# in the fronted to a QR image
ey****.***.***
Scanning and Parsing
The QR code must be decoded and parsed as a JWT. This JWT contains the ff standard fields (w/c may include additional fields depending on the service)
typ
the type of the JWT which is usually the service where the QR code was generatedsub
id of the document associated to the JWTaccessToken
(optional) access token that can be used to re/query all relevant encoded data in the JWT
const decodedFromQRCode = 'ey***.***.****';
const payload = parsedJWTPayload(decodedFromQRCode);
// { typ: 'medical-record', sub: 'randomid', accessToken: 'ey****.***.***' }
const requeried = await http.get(`/medical-records/${payload.sub}`, {
headers: { Authorization: `Bearer ${payload.accessToken}` }
});
// { id: 'randomid', ... }
const decodedFromQRCode = 'ey***.***.****';
const payload = parsedJWTPayload(decodedFromQRCode);
// { typ: 'medical-record', sub: 'randomid', accessToken: 'ey****.***.***' }
const requeried = await http.get(`/medical-records/${payload.sub}`, {
headers: { Authorization: `Bearer ${payload.accessToken}` }
});
// { id: 'randomid', ... }
Medical Encounter
MedicalEncounter
s represents a patient's journey/visit. it would be used to associate multiple MedicalRecord
s, the Billing
information, Diagnostic
records, and other services rendered to the patient
Creating Encounters
A medical encounter can be started using the medical-encounters
API's create
method.
Notes
- A create payload with
invoice: true
will auto create an associatedBillingInvoice
.
Finishing Encounters
MedicalEncounter
s should be marked as finished at the end of the actual patient visit as it would cascade to finalizing the associated MedicalRecord
s created during the visit (they would be considered drafts otherwise). To finalize an MedialEncounter
, a special patch
operator finish: true
can be use in the medical-encounters
API's patch
method.
Example
curl <base-url>/medical-encounters/<encounter-id> \
-X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>"
-d "{
"finish": true,
}"
curl <base-url>/medical-encounters/<encounter-id> \
-X PATCH \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>"
-d "{
"finish": true,
}"