Skip to main content

Laboratory Service — Application Logic

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD


1. Use Cases

Commands

Use caseCommandActorPreconditions
Create accession from orderCreateAccessionCommandLab clerk / system (order event)ServiceRequest exists in orders-service
Record specimen collectionRecordSpecimenCollectionCommandLab collectorAccession in Ordered or Received state
Mark specimen receivedMarkSpecimenReceivedCommandLab receiving staffAccession in Collected state
Enter lab resultEnterLabResultCommandLab technologistAccession in InProcess state
Verify resultVerifyLabResultCommandLab technologist (with lab:verify scope)Result in Draft state
Release resultsReleaseLabResultsCommandPathologist / authorized techAt least one result in Verified state
Correct resultCorrectLabResultCommandLab technologistResult in Verified or Released state
Acknowledge resultAcknowledgeResultCommandClinicianResult in Released state
Cancel accessionCancelAccessionCommandLab supervisorAccession not in Released state
Create test catalog itemCreateTestCatalogItemCommandLab adminValid LOINC code (if provided)
Set critical value policySetCriticalValuePolicyCommandLab adminTest code exists in catalog

Queries

Use caseQueryReturns
Fetch worklistGetWorklistQueryFiltered, paginated accession list
Get accession detailGetAccessionQueryFull accession + specimens + results
Get results for patientGetPatientResultsQueryPaginated DiagnosticReport list
Get result queueGetResultQueueQueryUnacknowledged / critical results for clinician
Trending for analyteGetAnalyteTrendQueryTime-series observations for a LOINC code
Lookup test catalogSearchTestCatalogQueryPaginated catalog items

2. Orchestration Flows

2.1 Order-to-Accession Flow

2.2 Result Entry → Verification → Release Flow

2.3 Critical Value Alert Flow


3. Ports

Port (interface)DirectionAdapter
IOrdersPortInboundNATS inbox consumer for clinical.orders.placed
IFhirPortOutboundHTTP adapter → interop-service FHIR gateway
ITerminologyPortOutboundHTTP adapter → terminology-service
IEventPublisherOutboundNATS JetStream publisher
ILaboratoryRepositoryOutboundDrizzle ORM → PostgreSQL
ICriticalAlertPortOutboundNATS event (consumed by communication-service)
IAuditPortOutboundNATS event (consumed by audit-service)

4. Saga / Outbox Pattern

Outbox

All domain events are written atomically with state changes using the transactional outbox pattern:

  1. Domain command executes; state change + event row written in same DB transaction.
  2. Outbox relay reads unpublished events and publishes to NATS.
  3. On NATS ack, event row marked published.

Critical Value Escalation Saga

  1. LabCriticalValueTriggered published.
  2. communication-service delivers alert to responsible clinician.
  3. If no LabResultAcknowledged within policy window, communication-service republishes escalation.
  4. Escalation continues until ack received or max-escalation level reached (tracked in critical_ack_attempts).

5. Error Handling

ScenarioStrategy
Order event missing patient referenceReject with LAB_ORDER_PATIENT_NOT_FOUND; DLQ
FHIR publish fails on releaseRetry via outbox; release action rolls back until FHIR confirm
Duplicate result entryIdempotency key on (accessionId, testCode, enteredBy, timestamp)
Analyzer import parse errorStore raw payload in analyzer_raw_messages; raise LAB_ANALYZER_PARSE_ERROR
Terminology lookup unavailableWarn + proceed with local catalog fallback; flag result terminology_unvalidated=true