Healthcare Service
A HealthcareService is a service a facility offers — cardiology, lab, radiology, pharmacy — scoped to one or more locations and to the facility organization that manages it. You touch it when modeling what a facility provides and where.
The Django model is thin storage: service_type and styling_metadata are opaque JSONFields. Their real structure lives in the Pydantic resource specs, which also define the bound value set, the internal_type enum, and the separate read and write API schemas.
Source:
- Model:
care/emr/models/healthcare_service.py - Spec:
care/emr/resources/healthcare_service/spec.py - Value set:
care/emr/resources/healthcare_service/valueset.py
Models
| Model | Purpose |
|---|---|
HealthcareService | A service a facility offers (e.g. cardiology, lab, radiology), scoped to locations and a managing organization |
HealthcareService extends EMRBaseModel, the shared Care EMR base that provides external_id, audit fields, soft-delete via deleted, created_by/updated_by, and history/meta JSON.
HealthcareService fields
Identity & classification
| Field | Type | Notes |
|---|---|---|
name | CharField(1024) | Display name. Required on write; no default |
service_type | JSONField → Coding | Holds one FHIR-style Coding object, not a string. Defaults to {}. In the API it is a ValueSetBoundCoding bound to the Healthcare Service Type Code value set (below). Optional (None) |
internal_type | CharField(255) | Nullable, default None. The API constrains it to the HealthcareServiceInternalType enum (pharmacy / lab / scheduling / store); the column does not |
extra_details | TextField | Free text. Not nullable and no DB default, so write specs require a value — an empty string counts |
Scope & placement
| Field | Type | Notes |
|---|---|---|
facility | FK → facility.Facility | PROTECT; nullable (default=None, blank=True). Excluded from every spec (__exclude__ = ["facility"]) and set server-side from the URL context — never from the request body |
locations | ArrayField[int] | Defaults to []. Holds FacilityLocation primary-key integers, not FK rows. Write specs take location external_ids (UUIDs); retrieve specs return serialized location objects |
managing_organization | FK → emr.FacilityOrganization | PROTECT; nullable. The facility-scoped org (department/team) responsible for the service. Write specs take its external_id (UUID), resolved server-side |
Presentation
| Field | Type | Notes |
|---|---|---|
styling_metadata | JSONField → dict | Nullable in the DB; defaults to {} in the specs. An open JSON bag of UI hints (colors, icons) with no backend semantics |
Coded field shapes (JSON fields)
service_type → Coding
service_type stores a single Coding object. In the API it is a ValueSetBoundCoding whose code is checked against the Healthcare Service Type Code value set during de-serialization. Optional (None).
Coding {
system: str | None # e.g. "http://terminology.hl7.org/CodeSystem/service-type"
version: str | None
code: str # required; validated against the bound value set
display: str | None
}
# extra="forbid" — unknown keys rejected
Bound value set — Healthcare Service Type Code
| Property | Value |
|---|---|
| Name | Healthcare Service Type Code |
| Slug | healthcare-service-type-code |
| Status | active |
| Compose / include system | http://terminology.hl7.org/CodeSystem/service-type |
| System version | 2.0.0 |
Registered via register_valueset(...) and register_as_system(). The service_type.code on create or update must resolve within this value set.
Enums
HealthcareServiceInternalType values
Constrains internal_type in the specs (str enum). The model column is a plain CharField, so legacy or other values may already exist in storage.
| Value |
|---|
pharmacy |
lab |
scheduling |
store |
Related models
facility.Facility
facility → FK Facility (PROTECT, nullable)
The facility offering the service. PROTECT blocks deleting a facility that still has healthcare services. Excluded from specs and set from the request context. See Facility.
emr.FacilityOrganization
managing_organization → FK FacilityOrganization (PROTECT, nullable)
The facility-scoped organization (department/team) that owns the service. Write specs take its external_id (UUID); the retrieve spec embeds it, serialized via FacilityOrganizationReadSpec. See Organization.
Locations
locations is an ArrayField of integer PKs, not a relational join — each entry references a FacilityLocation row by primary key, with resolution and validation handled in application code rather than by a database foreign key. Write specs take location external_ids (UUIDs); the retrieve spec embeds each location, serialized via FacilityLocationListSpec. See Location.
Resource specs (API schema)
Every spec extends EMRResource (care/emr/resources/base.py), which provides serialize (DB object → spec) and de_serialize (spec → DB object), plus the perform_extra_serialization / perform_extra_deserialization hooks. __exclude__ = ["facility"] keeps facility out of every payload.
| Spec class | Role | Notes |
|---|---|---|
BaseHealthcareServiceSpec | shared base | Fields: id, service_type, internal_type, name, styling_metadata, extra_details. __model__ = HealthcareService, __exclude__ = ["facility"] |
HealthcareServiceWriteSpec | write · create & update | Base fields plus locations: list[UUID4] (default []) and managing_organization: UUID4 | None. Resolves managing_organization from its external_id in perform_extra_deserialization |
HealthcareServiceReadSpec | read · list | Base fields. perform_extra_serialization sets id to obj.external_id |
HealthcareServiceRetrieveSpec | read · detail | Extends ReadSpec; overrides locations: list[dict] (each location serialized via FacilityLocationListSpec) and managing_organization: dict | None (serialized via FacilityOrganizationReadSpec) |
Field exposure by spec
| Field | Base | Write | Read (list) | Retrieve (detail) |
|---|---|---|---|---|
id (UUID4) | ✓ (read-only) | ✓ | ✓ (= external_id) | ✓ (= external_id) |
name (str, required) | ✓ | ✓ | ✓ | ✓ |
service_type (bound Coding, optional) | ✓ | ✓ | ✓ | ✓ |
internal_type (enum, optional) | ✓ | ✓ | ✓ | ✓ |
styling_metadata (dict, default {}) | ✓ | ✓ | ✓ | ✓ |
extra_details (str, required) | ✓ | ✓ | ✓ | ✓ |
locations | — | list[UUID4] (write) | — | list[dict] (embedded) |
managing_organization | — | UUID4 | None (write) | — | dict | None (embedded) |
Validation & server-side behaviour
service_type— aValueSetBoundCoding. De-serialization runsvalidate_valuesetoncodeagainst thehealthcare-service-type-codevalue set, andextra="forbid"on the underlyingCodingrejects unknown keys.managing_organization(write) —perform_extra_deserializationresolves the UUID viaget_object_or_404(FacilityOrganization, external_id=...)and assigns the FK; a falsy value setsmanaging_organization = None.locations(write) — submitted as UUIDs. The retrieve spec resolves each PK back to aFacilityLocationand serializes it, silently skipping any that fail to load (try/except … pass).id/external_id— never written from the body.de_serializeskips both;serialize/perform_extra_serializationpopulateidfromobj.external_id.facility— excluded from all specs and assigned server-side, so it can't be set or changed through the API body.- No
statusfield, and therefore no server-maintainedstatus_history.
Methods & save behaviour
- Inherits
save(), soft-delete (deleted), audit fields (created_by/updated_by),history/meta, andexternal_idfromEMRBaseModel. EMRResource.serialize/de_serializedrive read/write conversion; the extra (de)serialization hooks above handle FK resolution and embedded serialization.facilityandmanaging_organizationuseon_delete=PROTECT, so deleting either while a service references it is blocked at the DB level.
API integration notes
The API surface is built from the spec classes, not the raw model. Three things commonly trip up integrators:
service_typetakes aCodingobject whosecodeis in the bound value set, not a bare string.- On write,
locationsandmanaging_organizationareexternal_ids (UUIDs); detail responses embed the full objects. Nothing at the DB level confirms the referenced locations belong to the samefacility. facilityis never accepted in the request body — it's set from the URL context.
Related
- Reference: Facility
- Reference: Organization
- Reference: Location
- Reference: Value set
- Reference: Base models & conventions
- Source: healthcare_service.py model on GitHub
- Source: healthcare_service spec.py on GitHub
- Source: healthcare_service valueset.py on GitHub