Skip to main content
Version: 3.0

Specimen

A Specimen is a physical sample — blood, tissue, swab — collected from a patient for laboratory analysis. You create one to fulfill a lab order, then update it as the specimen moves through collection, receipt, and processing.

Several of the model's fields (care/emr/models/specimen.py) are opaque JSONFields whose structure lives only in the Pydantic resource specs (care/emr/resources/specimen/). The specs define the enums, nested JSON shapes, value-set bindings, validation, and the read/write schemas, so you need both layers to work with this resource.

Source:

Models

Specimen extends EMRBaseModel, the shared Care EMR base providing external_id, audit fields, soft-delete via deleted, and history/meta JSON.

Specimen fields

Identity & status

FieldModel typeSpec shape / valuesNotes
accession_identifierCharField(255), db_index=Truestr, default ""Lab accession/barcode identifier; indexed for lookup. Defaults to "", so it's optional on write.
statusCharField(20)SpecimenStatusOptions enumRequired on base/create, optional on update. See status values.
specimen_typeJSONFieldCoding bound to value set system-specimen_type-codeKind of material collected, as a single coding. Required on base/create, optional on update.
FieldModel typeNotes
facilityFK → FacilityPROTECT, nullable; the facility the specimen belongs to. Excluded from all specs (__exclude__).
patientFK → PatientCASCADE; the patient the specimen was collected from. Set on create via subject_patient (UUID).
encounterFK → EncounterCASCADE, nullable; the encounter during which collection occurred. Set on create via subject_encounter (UUID).
service_requestFK → ServiceRequestCASCADE, nullable; the order this specimen fulfills. Set on create via request (UUID); excluded from base/read field copy.
specimen_definitionFK → SpecimenDefinitionCASCADE, nullable; the definition/template this specimen was derived from.

Collection & processing

FieldModel typeSpec shapeNotes
collectionJSONField default=dictCollectionSpec | None, default NoneA single collection event: collector, method, body site, quantity, fasting. See CollectionSpec.
received_timeDateTimeField, nullablestr | None, default NoneWhen the lab received the specimen; ISO 8601 string in the spec.
conditionJSONField default=listlist[Coding] bound to system-specimen-condition-code, default []Coded conditions/state of the specimen on receipt.
processingJSONField default=listlist[ProcessingSpec], default []Processing steps applied. See ProcessingSpec.
noteTextField, nullablestr | None, default NoneFree-text annotation.

Enums

SpecimenStatusOptions values

The status enum (str). Two things to watch: entered_in_error uses an underscore rather than the FHIR hyphen, and draft is a Care addition with no FHIR equivalent.

ValueMeaning
draftCare-specific; not from FHIR
availableSpecimen available for testing
unavailableSpecimen no longer available
unsatisfactorySpecimen unsuitable for testing
entered_in_errorRecorded in error

Nested JSON specs

These define the real structure behind the model's JSONFields.

CollectionSpec

Shape of the collection JSON field — a single collection event.

FieldTypeRequiredNotes
collectorUUID4 | NoneoptionalExternal ID of the collecting User. Validated to exist (User.objects.filter(external_id=...)), else rejected with "Collector user not found". Serialized output adds collector_object, the resolved UserSpec from cache.
collected_date_timedatetime | NoneoptionalWhen the specimen was collected.
quantityQuantitySpec | NoneoptionalAmount collected. See QuantitySpec.
methodCoding | None bound to system-collection-method-codeoptionalCollection method (SNOMED). See collection method values.
procedureUUID4 | NoneoptionalReference to a procedure.
body_siteCoding | None bound to system-body-site-observationoptionalAnatomical site collected from.
fasting_status_codeable_conceptCoding | None bound to system-fasting-status-codeoptionalPatient fasting status (HL7 v2-0916).
fasting_status_durationDurationSpec | NoneoptionalFasting duration. See DurationSpec.

ProcessingSpec

One element of the processing list.

FieldTypeRequiredNotes
descriptionstrrequiredDescription of the processing step.
methodCoding | None bound to system-specimen-processing-method-codeoptionalProcessing method (SNOMED, descendants of 9265001).
performerUUID4 | NoneoptionalExternal ID of the performing User. Validated to exist, else rejected with "Performer user not found". Serialized output adds performer_object, the resolved UserSpec from cache.
time_date_timestrrequiredWhen the step was performed.

QuantitySpec

FieldTypeNotes
valueDecimalmax_digits=20, decimal_places=0, so integer-valued.
unitCodingRequired unit coding.

This is a specimen-local quantity spec, distinct from the shared Quantity common type — which allows decimal_places=6, optional value/unit, plus code/meta.

DurationSpec

FieldTypeNotes
valueintDuration magnitude.
unitCodingRequired unit coding.

Coding (shared common type)

Every coded field above uses Coding (extra="forbid"):

FieldTypeRequired
systemstr | Noneoptional
versionstr | Noneoptional
codestrrequired
displaystr | Noneoptional

Bound value sets

Coded fields bind to Care value sets via ValueSetBoundCoding[<slug>], which validates the submitted code against the value set at write time.

FieldValue setSlugSource system
specimen_typeSpecimen Type Codesystem-specimen_type-codeHL7 v2-0487
condition[]Specimen Conditionsystem-specimen-condition-codeHL7 v2-0493 (v2.0.0)
collection.methodCollection Methodsystem-collection-method-codeSNOMED CT (enumerated, see below)
collection.body_siteBody Sitesystem-body-site-observation(observation body-site value set)
collection.fasting_status_codeable_conceptFasting Statussystem-fasting-status-codeHL7 v2-0916 (v2.0.0)
processing[].methodSpecimen Processing Methodsystem-specimen-processing-method-codeSNOMED CT (< 9265001)

Collection Method value set

The system-collection-method-code value set enumerates these SNOMED CT codes:

CodeDisplay
129316008Aspiration - action
129314006Biopsy - action
129300006Puncture - action
129304002Excision - action
129323009Scraping - action
73416001Urine specimen collection, clean catch
225113003Timed urine collection
70777001Urine specimen collection, catheterized
386089008Collection of coughed sputum
278450005Finger-prick sampling

The other coded fields aren't enumerated. Fasting Status (http://terminology.hl7.org/CodeSystem/v2-0916), Specimen Condition (v2-0493), Specimen Type (v2-0487), Body Site, and Specimen Processing Method (SNOMED < 9265001) are pulled in by code-system reference or filter rather than a fixed concept list.

Resource specs (API schema)

Every spec extends EMRResource (care/emr/resources/base.py), which provides serialize (DB object → pydantic, via get_database_mapping) and de_serialize (pydantic → DB object), plus the perform_extra_serialization / perform_extra_deserialization hooks. __exclude__ = ["facility", "request"] on the base keeps those fields from being copied field-for-field.

Spec classRoleKey fields / behaviour
BaseSpecimenSpecshared baseid, accession_identifier, status (required), specimen_type (required), received_time, collection, processing, condition, note. __model__ = Specimen, __exclude__ = ["facility", "request"].
SpecimenCreateSpecwrite · createAdds subject_patient: UUID4 (required), subject_encounter: UUID4 (required), request: UUID4 | None. Wires up the FK links on creation.
SpecimenUpdateSpecwrite · updateRelaxes status and specimen_type to optional (| None) for partial updates.
SpecimenReadSpecread · listAdds specimen_definition: dict | None. perform_extra_serialization sets id = external_id and, when present, embeds the linked specimen definition via SpecimenDefinitionReadSpec.serialize(...).to_json().
SpecimenRetrieveSpecread · detailExtends SpecimenReadSpec, adds service_request: dict | None; serialization additionally embeds the linked service request via ServiceRequestReadSpec.serialize(...).to_json().

Nested specs (defined in the same module): CollectionSpec, ProcessingSpec, QuantitySpec, DurationSpec — see Nested JSON specs.

Validation & server behaviour

  • collection.collector and processing[].performer must reference existing users by external_id; serialization then injects the resolved collector_object / performer_object (cached UserSpec).
  • Coded fields are validated against their value sets on write (ValueSetBoundCoding); an unbound or invalid code is rejected.
  • Read specs embed related resources — specimen definition on list and detail, service request on detail — as nested JSON rather than bare IDs.
  • The base spec doesn't override perform_extra_deserialization, so no status_history-style server-side history is appended on write, unlike some other clinical resources.

API integration notes

  • Aligned with the FHIR Specimen resource, though some Care field names differ. On create, subject_patient / subject_encounter / request map to the patient / encounter / service_request FKs.
  • The viewset (SpecimenViewSet) mixes in retrieve and update only (EMRRetrieveMixin, EMRUpdateMixin) — so you get read/detail/list and update, with pydantic_model = BaseSpecimenSpec, pydantic_update_model = SpecimenUpdateSpec, pydantic_read_model = SpecimenReadSpec, pydantic_retrieve_model = SpecimenRetrieveSpec.
  • Filtering: accession_identifier (icontains); ordering on created_date / modified_date.
  • The custom action POST retrieve_by_accession_identifier looks up a specimen by accession_identifier (must be ≥ 5 chars), returning a SpecimenRetrieveSpec. It raises a validation error on no match or multiple matches.
  • Authorization keys off the linked service_request: read via can_read_specimen, write via can_write_specimen. One service request may own multiple specimens.
facility → FK Facility (PROTECT, nullable) [excluded from specs]
patient → FK Patient (CASCADE) [set via subject_patient]
encounter → FK Encounter (CASCADE, nullable) [set via subject_encounter]
service_request → FK ServiceRequest (CASCADE, nullable) [set via request]
specimen_definition → FK SpecimenDefinition (CASCADE, nullable)

A Specimen is created to fulfill a ServiceRequest (a lab order) and may be shaped by a SpecimenDefinition describing the expected sample. Results derived from a specimen surface through a DiagnosticReport.