References/Medication Request: Difference between revisions
More languages
More actions
OHC identity seed |
Automated edit (via update-page on MediaWiki MCP Server) |
||
| Line 504: | Line 504: | ||
* Updates reach only <code>status</code>, <code>note</code>, and <code>dispense_status</code>. |
* Updates reach only <code>status</code>, <code>note</code>, and <code>dispense_status</code>. |
||
* <code>requester</code>, <code>requested_product</code>, and <code>prescription</code> use <code>SET_NULL</code>, so a request outlives the user, product, or prescription it referenced. |
* <code>requester</code>, <code>requested_product</code>, and <code>prescription</code> use <code>SET_NULL</code>, so a request outlives the user, product, or prescription it referenced. |
||
{{Navbox medications}} |
|||
{{Related}} |
{{Related}} |
||
Latest revision as of 09:44, 6 July 2026
A MedicationRequest records a prescriber's intent to supply or administer a medication to a patient — the FHIR [https://hl7.org/fhir/medicationrequest.html MedicationRequest] resource. You create one whenever a drug is ordered during an encounter; it carries the medication, dosage instructions, timing, and route as structured JSON, grouped under a prescription.
Source:
- Model: [https://github.com/ohcnetwork/care/blob/develop/care/emr/models/medication_request.py
care/emr/models/medication_request.py] - Spec: [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/medication/request/spec.py
resources/medication/request/spec.py] - Spec: [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/medication/request_prescription/spec.py
resources/medication/request_prescription/spec.py] - Value sets: [https://github.com/ohcnetwork/care/tree/develop/care/emr/resources/medication/valueset
resources/medication/valueset/]
Several fields are opaque JSONFields whose structure the Django model never declares. The contract lives in the Pydantic resource specs under care/emr/resources/medication/request/: the enums, the nested shape of those JSON fields, validation rules, the read/write schema split, and the server-side side effects. The tables below merge both layers.
Models
| Model | Purpose |
|---|---|
MedicationRequestPrescription
|
Groups medication requests authored together for an encounter (a prescription) |
MedicationRequest
|
A single medication order/request for a patient within an encounter |
Both extend EMRBaseModel, which supplies external_id, created_date/modified_date, soft-delete via deleted, created_by/updated_by, and history/meta JSON.
MedicationRequest fields
Order status & intent
| Field | Type | Required | Notes |
|---|---|---|---|
status |
CharField(100) → MedicationRequestStatus |
Yes (spec) | |
status_reason |
CharField(100) → StatusReason |
No | |
intent |
CharField(100) → MedicationRequestIntent |
Yes (spec) | |
category |
CharField(100) → MedicationRequestCategory |
Yes (spec) | |
priority |
CharField(100) → MedicationRequestPriority |
Yes (spec) | |
do_not_perform |
BooleanField → bool |
Yes | |
dispense_status |
CharField(100) → MedicationRequestDispenseStatus |
No |
Medication & dosage
| Field | Type | Required | Notes |
|---|---|---|---|
medication |
JSONField → ValueSetBoundCoding[system-medication] |
Conditional | |
method |
JSONField |
n/a | |
dosage_instruction |
JSONField → list[DosageInstruction] |
Yes | |
note |
TextField → str |
No |
Subject & provenance
| Field | Type | Required | Notes |
|---|---|---|---|
patient |
FK → Patient |
server-set | |
encounter |
FK → Encounter |
Yes (create) | |
authored_on |
DateTimeField → datetime |
Yes (spec) | |
requester |
FK → users.User |
No | |
requested_product |
FK → ProductKnowledge |
Conditional | |
prescription |
FK → MedicationRequestPrescription |
No |
Enum values
Spec enums use underscored member values (on_hold, entered_in_error, original_order), not the hyphenated FHIR spellings. These are the exact strings the API accepts and returns.
MedicationRequestStatus values
| Value |
|---|
active
|
on_hold
|
ended
|
stopped
|
completed
|
cancelled
|
entered_in_error
|
draft
|
unknown
|
StatusReason values
| Value | Meaning (FHIR) |
|---|---|
altchoice
|
Alternative choice |
clarif
|
Prescription requires clarification |
drughigh
|
Drug level too high |
hospadm
|
Admission to hospital |
labint
|
Lab interference issues |
non_avail
|
Patient not available |
preg
|
Patient is pregnant or breastfeeding |
salg
|
Allergy |
sddi
|
Drug interaction |
sdupther
|
Duplicate therapy |
sintol
|
Suspected intolerance |
surg
|
Patient scheduled for surgery |
washout
|
Washout |
MedicationRequestIntent values
| Value |
|---|
proposal
|
plan
|
order
|
original_order
|
reflex_order
|
filler_order
|
instance_order
|
MedicationRequestPriority values
| Value |
|---|
routine
|
urgent
|
asap
|
stat
|
MedicationRequestCategory values
| Value |
|---|
inpatient
|
outpatient
|
community
|
discharge
|
MedicationRequestDispenseStatus values
| Value |
|---|
complete
|
partial
|
incomplete
|
declined
|
TimingUnit values
UCUM time units used by Timing.repeat.period_unit and bounds_duration.unit.
| Value | Unit |
|---|---|
s
|
second |
min
|
minute |
h
|
hour |
d
|
day |
wk
|
week |
mo
|
month |
a
|
year |
DoseType values
Used by DoseAndRate.type.
| Value |
|---|
ordered
|
calculated
|
DosageInstruction nested spec
Each entry in the dosage_instruction JSON list deserializes to a DosageInstruction (Pydantic, snake_case keys) — the structure hiding behind the opaque JSONField.
| Field | Type | Required | Notes |
|---|---|---|---|
sequence |
int |
No | |
text |
str |
No | |
additional_instruction |
list[Coding] |
No | |
patient_instruction |
str |
No | |
timing |
Timing |
No | |
as_needed_boolean |
bool |
Yes | |
as_needed_for |
Coding |
No | |
site |
Coding |
No | |
route |
Coding |
No | |
method |
Coding |
No | |
dose_and_rate |
DoseAndRate |
No | |
max_dose_per_period |
DoseRange |
No |
Sub-types under DosageInstruction
Timing {
repeat: TimingRepeat # required
code: Coding | None # e.g. BID/TID/QID timing abbreviation
}
TimingRepeat {
frequency: int # required — repetitions per period
period: Decimal(20,0) # required — duration the frequency applies to
period_unit: TimingUnit # required — s|min|h|d|wk|mo|a
bounds_duration: TimingQuantity # required — total span
}
TimingQuantity { # integer-valued time amount
value: Decimal(20,0) # required
unit: TimingUnit # required
}
DoseAndRate {
type: DoseType # required — ordered | calculated
dose_range: DoseRange | None # for titrated doses
dose_quantity: DosageQuantity | None # for regular doses
}
DoseRange {
low: DosageQuantity # required
high: DosageQuantity # required
}
DosageQuantity { # measured dose amount
value: Decimal(20,6) # required
unit: Coding # required
}
The Pydantic specs define these JSON keys as snake_case (as_needed_boolean, period_unit, dose_and_rate, max_dose_per_period, bounds_duration), so that is how they sit in storage — not the camelCase FHIR wire format.
Bound value sets
Coded fields bind to Care value sets through ValueSetBoundCoding[<slug>]. On write, the supplied Coding.code is validated against the value set; a code outside it is rejected. All draw from SNOMED CT (http://snomed.info/sct).
| Field | Value set slug | SNOMED CT scope |
|---|---|---|
medication
|
system-medication
|
<< 763158003 Medicinal product
|
dosage_instruction[].route
|
system-route
|
is-a 284009009 Route of administration
|
dosage_instruction[].site
|
system-body-site
|
is-a 91723000 Anatomical structure
|
dosage_instruction[].method
|
system-administration-method
|
is-a 736665006
|
dosage_instruction[].as_needed_for
|
system-as-needed-reason
|
is-a 404684003 Clinical finding
|
dosage_instruction[].additional_instruction
|
system-additional-instruction
|
is-a 419492006
|
system-medication-not-given lives in this directory too, but it binds on References/Medication Administration, not on the request.
Resource specs (API schema)
Every spec extends EMRResource, which provides serialize / de_serialize plus the perform_extra_serialization / perform_extra_deserialization hooks. MedicationRequestResource sets __exclude__ = [patient, encounter, requester, requested_product, prescription], so those relations are wired up by hand instead of auto-mapped.
| Spec class | Role | Notes |
|---|---|---|
MedicationRequestAbstractSpec
|
shared (fields) | Plain BaseModel holding the clinical fields: status, status_reason, intent, category, priority, do_not_perform, medication, dosage_instruction, authored_on, note, dispense_status
|
MedicationRequestResource
|
shared (binding) | Binds the spec to the MedicationRequest model and declares __exclude__
|
BaseMedicationRequestSpec
|
shared | MedicationRequestResource + MedicationRequestAbstractSpec + id: UUID4
|
MedicationRequestSpec
|
write · create | Adds encounter (UUID, required), requester, requested_product, prescription (UUIDs), and create_prescription. Carries the validators and perform_extra_deserialization
|
MedicationRequestUpdateSpec
|
write · update | Narrow — only status, note, dispense_status are mutable after create
|
MedicationRequestReadWithoutPrescriptionSpec
|
read · embedded | Full read minus prescription; expands requested_product (ProductKnowledgeReadSpec), requester/created_by/updated_by (UserSpec), plus created_date/modified_date
|
MedicationRequestReadSpec
|
read · detail/list | Adds expanded prescription (MedicationRequestPrescriptionReadSpec) and the encounter external id
|
CreatePrescription
|
write · nested | { name?, note?, alternate_identifier (required) } — inline prescription creation
|
Validation (create — MedicationRequestSpec)
- Medication XOR product: you cannot set both
medicationandrequested_product, and one is required. - Prescription XOR create: you cannot set both
prescriptionandcreate_prescription. - Encounter existence: the
encounterUUID must match an existingEncounter(field validator). authored_on, and any nestedPeriodSpec/timing datetimes, must be timezone-aware.
Server-side side effects (perform_extra_deserialization)
encounteris resolved from its UUID, thenpatientis copied fromencounter.patient— the client never setspatientdirectly.requester/requested_productare resolved byexternal_id. Ifrequested_product.facilityis set and differs fromencounter.facility, the write raises"Product not found in facility".prescriptionis resolved byexternal_id, scoped to the sameencounter.create_prescriptionlooks up an existing prescription by(alternate_identifier, encounter). A match that is notactiveraises"Prescription is not active"; no match creates a newMedicationRequestPrescription(status=active, copyingname/note,prescribed_by=requester) and links the request to it.
Serialization (read)
perform_extra_serialization sets id = external_id and expands requested_product, requester, and the audit users (created_by/updated_by) from cache. MedicationRequestReadSpec goes further, expanding prescription and emitting encounter as its external id.
Related models
MedicationRequestPrescription
The container that groups every medication request authored together for an encounter into one prescription. Each request points back via MedicationRequest.prescription.
encounter → FK Encounter (CASCADE)
patient → FK Patient (CASCADE)
name → CharField(100), nullable
note → TextField, nullable
prescribed_by → FK users.User (CASCADE, nullable)
status → CharField(100), nullable → MedicationRequestPrescriptionStatus
approval_status → CharField(100), nullable
alternate_identifier → CharField(100), nullable
tags → ArrayField[int], default []
A UniqueConstraint (unique_alternate_identifier_encounter) keeps alternate_identifier unique per encounter.
MedicationRequestPrescriptionStatus values
active, on_hold, ended, stopped, completed, cancelled, entered_in_error, draft.
A pharmacist may only move a prescription between active, on_hold, completed (MEDICATION_PRESCRIPTION_PHARMACIST_ALLOWED_STATUS).
Prescription specs
| Spec class | Role | Notes |
|---|---|---|
BaseMedicationRequestPrescriptionSpec
|
shared | id, status (MedicationRequestPrescriptionStatus), note, name
|
MedicationRequestPrescriptionWriteSpec
|
write · create | Adds encounter (UUID), prescribed_by (UUID); resolves encounter→patient and prescribed_by server-side
|
MedicationRequestPrescriptionUpdateSpec
|
write · update | Same shared fields, no new FKs |
MedicationRequestPrescriptionReadSpec
|
read · list | Adds created_date, modified_date, expanded prescribed_by (UserSpec), tags (rendered via SingleFacilityTagManager)
|
MedicationRequestPrescriptionRetrieveSpec
|
read · detail | Adds audit created_by/updated_by
|
MedicationRequestPrescriptionRetrieveMedicationsSpec
|
read · detail+children | Adds medications (each via MedicationRequestReadWithoutPrescriptionSpec) and full encounter (EncounterRetrieveSpec)
|
MedicationRequestPrescriptionRetrieveDetailedSpec
|
read · detail | Adds encounter via EncounterListSpec
|
Methods & save behaviour
- Read and write run through the inherited
EMRResource.serialize/de_serialize.de_serializedumps withexclude_defaults=True, maps the remaining fields onto the model, then callsperform_extra_deserializationfor the relation and prescription handling above. patientalways comes fromencounter; the client never writes it.- Inline prescription creation (
create_prescription) is idempotent on(alternate_identifier, encounter)and proceeds only when an existing match isactive. authored_onfalls back totimezone.nowat the model layer when omitted.
API integration notes
- Coded fields take a single
Codingobject{ system, code, display }validated against bound SNOMED CT value sets — send acodefrom the right value set or the write fails. - Enum members are underscored (
on_hold,entered_in_error,original_order); send those literals, not the FHIR hyphenated forms. dosage_instructioncarries SIG text, timing/frequency, PRN flags, dose and rate, and max-dose limits — write the full nested shape (snake_case keys) rather than free text alone.- On create, send either
medicationorrequested_product(not both) and at most one ofprescription/create_prescription. - Updates reach only
status,note, anddispense_status. requester,requested_product, andprescriptionuseSET_NULL, so a request outlives the user, product, or prescription it referenced.
Related
Pages that link here:
- Reference: References/Base models & conventions