Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

References/Observation

From OHC Network Wiki
Revision as of 09:33, 6 July 2026 by Admin (talk | contribs) (Automated edit (via update-page on MediaWiki MCP Server))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
referenceclinicalFHIR: ObservationCARE 3.0+

An Observation is one named, coded data point about a subject — almost always a patient: a blood pressure reading, a temperature, a coded answer captured through a questionnaire. main_code records what was observed (usually bound to LOINC) and value holds the result. You rarely create one by hand; most observations are materialized when a questionnaire is submitted.

Source:

The model is just storage; several fields are opaque JSONFields. Their real structure lives in the Pydantic resource specs under care/emr/resources/observation/, which own the enums, nested JSON shapes, validation, and the read/write schema split. Each field row below gives the storage column first, then the shape the spec enforces on top of it.

Models

Model Purpose
Observation A single coded measurement or finding about a patient, captured within an encounter

Observation extends EMRBaseModel, the shared Care EMR base that supplies external_id, created_date/modified_date, soft-delete via deleted, created_by/updated_by, and history/meta JSON.

Observation fields

Classification & coding

Field Storage type Spec shape / notes
status CharField(255) Enum ObservationStatusfinal, amended, entered_in_error. Required in specs. Questionnaire-sourced observations land as final
is_group BooleanField Default False. True marks a grouping/panel observation that holds component/child observations instead of a single value. Not exposed in the resource specs
category JSONField (default {}) Spec: optional Coding { system?, version?, code, display? }. FHIR observation category, derived from the questionnaire
main_code JSONField (default {}) Spec: optional Coding. What is being observed, typically LOINC (CARE_OBSERVATION_VALUSET, system http://loinc.org)
alternate_coding JSONField (default []) Spec: optional CodeableConcept { id?, coding?: Coding[], text }. Same concept expressed in other code systems

Subject & context

Field Storage type Spec shape / notes
subject_type CharField(255) Enum SubjectTypepatient, encounter. Spec defaults to encounter
subject_id UUIDField The subject entity's id. Set server-side; not in the spec body
patient FK → Patient CASCADE. Set server-side, not in the spec body
encounter FK → Encounter None. Where the observation was recorded
effective_datetime DateTimeField When the observation was effective. Nullable in storage, but the spec requires a tz-aware datetime on create; optional on update

Author & performer

Field Storage type Spec shape / notes
data_entered_by FK → users.User CASCADE, nullable. related_name="observations_entered". Write specs accept data_entered_by_id: int; read specs serialize a nested UserSpec
performer JSONField (default {}) user), id: str }. Use it when the performer differs from the data-entry user

Value

Field Storage type Spec shape / notes
value_type CharField(255) Enum QuestionType (from the questionnaire module). Tells the client how to read value — see the table below. Required in specs
value JSONField Spec: QuestionnaireSubmitResultValue { value?: str, unit?: Coding, coding?: Coding }. Required on create, optional on update. value holds the raw/string result, unit the quantity unit, coding the coded answer
note TextField None. Free-text note

Clinical qualifiers

Field Storage type Spec shape / notes
body_site JSONField (default {}) Spec: optional Coding bound to CARE_BODY_SITE_VALUESET (slug system-body-site-observation, SNOMED CT). FHIR Observation.bodySite
method JSONField (default {}) Spec: optional Coding bound to CARE_OBSERVATION_COLLECTION_METHOD (slug system-collection-method, SNOMED CT). FHIR Observation.method
reference_range JSONField (default []) Spec: ReferenceRange[] (shape below), default []. Reference ranges for the value, usually carried over from the observation definition
interpretation JSONField (default {}) Spec: free dict, default {}. Coded interpretation against the reference range (high/low/normal). Normal/abnormal/critical value sets exist (below) but are not enforced on this dict
interpretation_old CharField(255) Nullable. Legacy free-text interpretation, kept for backward compatibility. Not in the specs

Structure & relationships

Field Storage type Spec shape / notes
parent UUIDField None — the external_id of a parent observation, for nesting related observations
component JSONField (default []) Spec: Component[] (shape below), default []. Sub-observations sharing this context but carrying their own codes and values (FHIR Observation.component)
questionnaire_response FK → QuestionnaireResponse None. The submission that produced this observation
diagnostic_report FK → DiagnosticReport CASCADE, nullable. The report this observation belongs to, if any. Not in the write specs
observation_definition FK → ObservationDefinition CASCADE, nullable. The definition this observation templates from. Serialized as BaseObservationDefinitionSpec only in ObservationRetrieveSpec

Enum & value-set reference

ObservationStatus values

Value Meaning
final Recorded, complete and verified. The default for questionnaire-sourced observations
amended Was final, then corrected
entered_in_error Recorded in error; disregard it

PerformerType values (performer.type)

Value
related_person
user

SubjectType values (subject_type)

Value
patient
encounter (spec default)

QuestionType values (value_type)

From the questionnaire module. The value tells the client which key of value to read.

Value Value sourced from QuestionnaireSubmitResultValue
group grouping node (no direct value)
boolean value ("true"/"false")
decimal value
integer value
string value
text value
display display-only
date value
dateTime value
time value
choice coding
url value
quantity value + unit
structured structured payload

Bound value sets

Coded fields validate against registered Care value sets. A body_site or method coding outside its value set is rejected during deserialization.

Field Value set Slug System(s)
main_code CARE_OBSERVATION_VALUSET system-observation http://loinc.org
body_site CARE_BODY_SITE_VALUESET system-body-site-observation http://snomed.info/sct (curated concept list + descendants of 442083009)
method CARE_OBSERVATION_COLLECTION_METHOD system-collection-method http://snomed.info/sct (descendants of 272394005, 129264002, 386053000)

These interpretation value sets are registered for the frontend and observation definitions, but are not enforced on the interpretation dict:

Value set Slug Concepts (system http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation)
Normal system-normal-coded-valueset N Normal, ND Not detected, NEG Negative
Abnormal system-abnormal-coded-valueset A Abnormal, AA Critically abnormal, H High, HH Critically high, L Low, LL Critically low, POS Positive, DET Detected
Critical system-critical-coded-valueset C Critical, CC Critical high, CL Critical low, CV Critical value
UCUM units system-ucum-units http://unitsofmeasure.org (all UCUM units)

Nested JSON shapes (from the spec)

The structures behind the model's JSONFields.

Coding

Coding {
  system:  str | null      # e.g. http://loinc.org
  version: str | null
  code:    str             # required
  display: str | null
}                          # extra keys forbidden

CodeableConcept (alternate_coding)

CodeableConcept {
  id:     str | null
  coding: Coding[] | null
  text:   str | null       # field present, required key
}                          # extra keys forbidden

QuestionnaireSubmitResultValue (value)

QuestionnaireSubmitResultValue {
  value:  str | null       # raw/string value
  unit:   Coding | null    # for quantity values
  coding: Coding | null    # for coded values
}

Performer (performer)

Performer {
  type: PerformerType      # related_person | user
  id:   str
}

ReferenceRange (reference_range[])

ReferenceRange {
  min:            float | null
  max:            float | null
  unit:           str | null
  interpretation: str        # required
  value:          str | null
}

Component (component[])

Component {
  value:           QuestionnaireSubmitResultValue   # required
  interpretation:  str | dict     = {}
  reference_range: ReferenceRange[] = []
  code:            Coding | null   = null
  note:            str            = ""
}

Resource specs (API schema)

The Pydantic specs build on [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py EMRResource], which provides serialize / de_serialize and the perform_extra_serialization / perform_extra_deserialization hooks. Every concrete spec inherits from BaseObservationSpec.

Spec Role Notes
BaseObservationSpec shared base Defines the common fields: id, status, category, main_code, alternate_coding, subject_type, encounter, effective_datetime, performer, value_type, value, note, body_site (bound), method (bound), reference_range, interpretation, parent, questionnaire_response, component
ObservationSpec write · create Adds data_entered_by_id, created_by_id, updated_by_id (all int). Used internally when materializing observations from a questionnaire submission
ObservationUpdateSpec write · update The base, but effective_datetime and value relax to optional (None) for partial updates
ObservationReadSpec read · list Swaps the user IDs for nested created_by / updated_by / data_entered_by UserSpec objects
ObservationRetrieveSpec read · detail Extends ObservationReadSpec and additionally serializes observation_definition via BaseObservationDefinitionSpec when it is set

Server-side behaviour

  • ObservationSpec.perform_extra_deserialization (create/update): sets obj.external_id = self.id, copies data_entered_by_id, created_by_id, updated_by_id onto the model, drops data_entered_by_id from meta, and on create (is_update is false) clears obj.id so a new row is inserted.
  • ObservationReadSpec.perform_extra_serialization: maps id from external_id; deliberately blanks encounter, patient, and questionnaire_response to None in the output to avoid extra DB queries; resolves the audit users (created_by, updated_by) and data_entered_by from cache (model_from_cache).
  • ObservationRetrieveSpec.perform_extra_serialization: calls the parent, then inlines the full observation_definition when the FK is set.
  • body_site / method are ValueSetBoundCoding[...]: the supplied Coding is validated against its bound value set during deserialization and rejected if the code is not a member.
  • de_serialize only writes fields present in the model's column mapping. Non-default values are persisted (model_dump(exclude_defaults=True)), and unknown spec-only fields would land in meta when __store_metadata__ is set — which, by default, it is not for observations.

Observation is self-contained; it expresses relationships through foreign keys rather than secondary tables.

patient                → FK Patient (CASCADE)
encounter              → FK Encounter (CASCADE)
data_entered_by        → FK users.User (CASCADE, nullable)
questionnaire_response → FK QuestionnaireResponse (CASCADE, nullable)
diagnostic_report      → FK DiagnosticReport (CASCADE, nullable)
observation_definition → FK ObservationDefinition (CASCADE, nullable)

parent is the exception: a soft, UUID-based self-reference to another observation's external_id, not a Django FK. It lets observations nest without a database constraint.

API integration notes

  • Observations are exposed through Care's REST API and align with the FHIR Observation resource. FHIR field names (effectiveDateTime, bodySite, and so on) differ from the Django model names; the resource specs above are the authoritative request/response schemas.
  • Most observations are created as a side effect of submitting a questionnaire. value and value_type mirror the submission types (QuestionnaireSubmitResultValue / QuestionType), and questionnaire_response records provenance.
  • effective_datetime must be timezone-aware. Required on create, optional on update.
  • status is one of final / amended / entered_in_error; questionnaire-sourced observations are final.
  • body_site and method are validated against their bound value sets, and main_code is expected to bind to LOINC via CARE_OBSERVATION_VALUSET.
  • On read, the list and detail specs blank out encounter, patient, and questionnaire_response, so don't rely on those being populated in observation payloads.
  • Prefer structured observations. Allergy and medication checks read coded values, not free text, so unstructured data leaves them blind.

Pages that link here:

Wiki: ohcnwiki.tellmey.fyi