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

References/Service Request

From OHC Network Wiki
Revision as of 04:14, 5 July 2026 by Admin (talk | contribs) (OHC identity seed)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
referenceclinicalFHIR: ServiceRequestCARE 3.0+

A ServiceRequest is an order or proposal to perform an action — clinical or otherwise — for a patient (FHIR ServiceRequest). It drives the creation of specimens, diagnostic reports, observations, and procedures, each of which links back to the originating request. Care implements a minimal subset of the FHIR spec.

Source:

The Django model is only storage: several columns are opaque JSONFields and free-text CharFields. Their real structure, enums, bound value sets, and read/write API schemas live in the Pydantic resource specs (care/emr/resources/service_request/spec.py). Both layers are covered below.

Models

Model Purpose
ServiceRequest An order or proposal to perform an action for a patient

ServiceRequest extends EMRBaseModel, the shared Care EMR base that supplies external_id, audit fields created_by/updated_by, created_date/modified_date, meta, and soft-delete semantics — see Base model.

ServiceRequest fields

Request definition

Field Model type Spec type / shape Notes
title CharField(1024) str Human-readable summary. Required on create, optional on update.
category CharField(255) ActivityDefinitionCategoryOptions enum Coded category. Required on create. See [[#category-values
status CharField(255) ServiceRequestStatusChoices enum Lifecycle status. Required on create. See [[#status-values
intent CharField(255) ServiceRequestIntentChoices enum Required on create. See [[#intent-values
priority CharField(255) ServiceRequestPriorityChoices enum Required on create. See [[#priority-values
do_not_perform BooleanField None True flags the service/procedure as explicitly not to be performed. Model default False; spec default None, so it's omitted from writes unless set.
code JSONField (nullable) Coding bound to activity-definition-procedure-code The requested service/procedure. Required on create. A single Coding, not a CodeableConcept, validated against the bound value set.
body_site JSONField (nullable) Coding bound to system-body-site-observation, optional Coded location on the body. A single Coding, validated against the bound value set.

A bound Coding (ValueSetBoundCoding) has the shape:

{
  "system": "<uri | null>",
  "version": "<str | null>",
  "code": "<str>",          // required; must resolve in the bound value set
  "display": "<str | null>"
}

Clinical detail

Field Model type Spec type Notes
note TextField (nullable) None Free-text comments.
patient_instruction TextField (nullable) None Instructions surfaced to the patient.
occurance DateTimeField (nullable) None When the request should take place. Spelled occurance in both model and spec — the typo is intentional, match it.

Relationships

Field Model type Spec type Notes
facility FK → facility.Facility (not in write spec) Owning facility. PROTECT. Set server-side from request context.
patient FK → emr.Patient (derived) Subject of the request. CASCADE. Not accepted from clients — set server-side from encounter.patient on create.
encounter FK → emr.Encounter (nullable) UUID4 (create only) Encounter the request was created in. CASCADE. Required as a UUID on Create; resolved via get_object_or_404. Read back as a serialized encounter dict.
healthcare_service FK → emr.HealthcareService (nullable) None Service fulfilling the request. PROTECT. Write accepts external_id; resolved server-side. Excluded from base serialize; returned only on Retrieve.
activity_definition FK → emr.ActivityDefinition (nullable) (read only) Template the request was created from. PROTECT. Serialized only on Retrieve.
requester FK → users.User (nullable) None (write) / dict | None (read) User who placed the request. CASCADE. Write accepts external_id; read returns a cached UserSpec dict.
locations ArrayField[int] list[UUID4] (write) / list[dict] (read) Facility-location IDs the request applies to. Model default []. Write accepts location external_ids, stored on obj._locations for the manager to persist; serialized as FacilityLocationListSpec dicts only on Retrieve.
tags ArrayField[int] list[dict] (read) Tag IDs. Model default []. Rendered via SingleFacilityTagManager().render_tags(obj) on read; not set directly from the write spec.

Enums

Status values

ServiceRequestStatusChoices values are snake_case, not the hyphenated FHIR codes.

Value Meaning
draft Request is being drafted, not yet actionable
active Request is active
on_hold Request is paused
entered_in_error Request was entered in error
ended Request has ended
completed Request has been fulfilled
revoked Request was revoked/cancelled

spec.py derives two groupings from these:

  • SERVICE_REQUEST_COMPLETED_CHOICES = completed, revoked, ended, entered_in_error (terminal states).
  • SERVICE_REQUEST_CANCELLED_CHOICES = revoked, entered_in_error.

There is no unknown status.

Intent values

ServiceRequestIntentChoices

Value
proposal
plan
directive
order

Priority values

ServiceRequestPriorityChoices

Value
routine
urgent
asap
stat

Category values

category reuses ActivityDefinitionCategoryOptions from care/emr/resources/activity_definition/spec.py.

Value
laboratory
imaging
counselling
surgical_procedure
education

Bound value sets

Each coded Coding field validates its code against a registered Care value set (ValueSetBoundCoding[...]).

Field Value set slug Composition
code activity-definition-procedure-code SNOMED CT is-a 71388002 (Procedure). See [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/activity_definition/valueset.py activity_definition/valueset.py].
body_site system-body-site-observation SNOMED CT — explicit limb/joint concepts plus is-a 442083009. See [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/observation/valueset.py observation/valueset.py].

Resource specs (API schema)

Every spec subclasses EMRResource (serialize / de_serialize, with perform_extra_serialization / perform_extra_deserialization hooks — see Base model). The base sets __model__ = ServiceRequest and __exclude__ = ["encounter", "healthcare_service", "locations"], so those three fields are handled only by the explicit per-spec hooks.

Spec class Role Adds / overrides
BaseServiceRequestSpec shared id, title, status, intent, priority, category, do_not_perform, note, code (required), body_site, occurance, patient_instruction
ServiceRequestWriteSpec write · shared Adds healthcare_service: UUID4?, locations: list[UUID4], requester: UUID4?. Resolves healthcare_service and requester from external_id; stashes locations on obj._locations.
ServiceRequestCreateSpec write · create Adds required encounter: UUID4. Resolves the encounter and sets obj.patient = obj.encounter.patient server-side.
ServiceRequestUpdateSpec write · update Makes title, status, intent, priority, category, code all optional for partial update.
ServiceRequestReadSpec read · list Adds created_date, modified_date, encounter (serialized via EncounterListSpec), tags (rendered), requester (cached UserSpec). Sets id = external_id.
ServiceRequestRetrieveSpec read · detail Extends Read with locations (FacilityLocationListSpec), healthcare_service (HealthcareServiceReadSpec), activity_definition (ActivityDefinitionReadSpec), specimens (SpecimenReadSpec), diagnostic_reports (DiagnosticReportListSpec), embedded encounter.patient (PatientRetrieveSpec), and audit created_by/updated_by.

Write-side behaviour (perform_extra_deserialization)

  • healthcare_service, when provided, is looked up by external_id and assigned.
  • requester, when provided, is looked up by external_id via get_object_or_404(User, ...).
  • locations: the list of UUIDs is stored on obj._locations; the persisting view/manager translates them to integer IDs for the locations array.
  • On create only, encounter is required, fetched via get_object_or_404(Encounter, ...), and obj.patient is forced to encounter.patient. Clients cannot set patient directly.

Read-side behaviour (perform_extra_serialization)

  • id is set to external_id; encounter is serialized with EncounterListSpec; tags come from SingleFacilityTagManager().render_tags(obj); requester, if set, is a cached UserSpec.
  • On retrieve only: queries FacilityLocation for obj.locations; serializes healthcare_service and activity_definition when present; fetches the related Specimen and DiagnosticReport rows that reference this request; embeds the patient (PatientRetrieveSpec, scoped to obj.facility) under encounter.patient; and attaches audit users.

Methods & save behaviour

  • ServiceRequest inherits save, soft-delete, and audit behaviour from EMRBaseModel (see Base model). The model defines no custom save override.
  • The Pydantic write specs enforce all write validation — enums, required code, bound value sets, encounter requirement — during de_serialize, not Django field choices. The DB columns are plain CharField/JSONField.
  • patient is never accepted from the client; it is derived from encounter.patient on create.
  • Related Specimen and DiagnosticReport records reference the request via their own service_request FK. The detail view (Retrieve) reads them back rather than storing them on the request.

API integration notes

Things that trip up integrators:

  • Spellings follow Care conventions, not FHIR: status/intent/priority are snake_case enum values, and occurance keeps its model typo.
  • code is required and body_site optional; both are single Coding objects validated against their bound value sets — not CodeableConcept.
  • category, status, intent, and priority are validated as enums by the spec even though the columns are free CharFields.
  • Write healthcare_service, requester, and locations as external_id/UUIDs and let the server resolve them. encounter (UUID) is required on create and determines the patient.
  • locations and tags store ID arrays for fast filtering — drive them through the location/tag managers rather than setting the raw arrays from clients.

Pages that link here: