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 case | Command | Actor | Preconditions |
|---|---|---|---|
| Create accession from order | CreateAccessionCommand | Lab clerk / system (order event) | ServiceRequest exists in orders-service |
| Record specimen collection | RecordSpecimenCollectionCommand | Lab collector | Accession in Ordered or Received state |
| Mark specimen received | MarkSpecimenReceivedCommand | Lab receiving staff | Accession in Collected state |
| Enter lab result | EnterLabResultCommand | Lab technologist | Accession in InProcess state |
| Verify result | VerifyLabResultCommand | Lab technologist (with lab:verify scope) | Result in Draft state |
| Release results | ReleaseLabResultsCommand | Pathologist / authorized tech | At least one result in Verified state |
| Correct result | CorrectLabResultCommand | Lab technologist | Result in Verified or Released state |
| Acknowledge result | AcknowledgeResultCommand | Clinician | Result in Released state |
| Cancel accession | CancelAccessionCommand | Lab supervisor | Accession not in Released state |
| Create test catalog item | CreateTestCatalogItemCommand | Lab admin | Valid LOINC code (if provided) |
| Set critical value policy | SetCriticalValuePolicyCommand | Lab admin | Test code exists in catalog |
Queries
| Use case | Query | Returns |
|---|---|---|
| Fetch worklist | GetWorklistQuery | Filtered, paginated accession list |
| Get accession detail | GetAccessionQuery | Full accession + specimens + results |
| Get results for patient | GetPatientResultsQuery | Paginated DiagnosticReport list |
| Get result queue | GetResultQueueQuery | Unacknowledged / critical results for clinician |
| Trending for analyte | GetAnalyteTrendQuery | Time-series observations for a LOINC code |
| Lookup test catalog | SearchTestCatalogQuery | Paginated 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) | Direction | Adapter |
|---|---|---|
IOrdersPort | Inbound | NATS inbox consumer for clinical.orders.placed |
IFhirPort | Outbound | HTTP adapter → interop-service FHIR gateway |
ITerminologyPort | Outbound | HTTP adapter → terminology-service |
IEventPublisher | Outbound | NATS JetStream publisher |
ILaboratoryRepository | Outbound | Drizzle ORM → PostgreSQL |
ICriticalAlertPort | Outbound | NATS event (consumed by communication-service) |
IAuditPort | Outbound | NATS event (consumed by audit-service) |
4. Saga / Outbox Pattern
Outbox
All domain events are written atomically with state changes using the transactional outbox pattern:
- Domain command executes; state change + event row written in same DB transaction.
- Outbox relay reads unpublished events and publishes to NATS.
- On NATS ack, event row marked
published.
Critical Value Escalation Saga
LabCriticalValueTriggeredpublished.- communication-service delivers alert to responsible clinician.
- If no
LabResultAcknowledgedwithin policy window, communication-service republishes escalation. - Escalation continues until ack received or max-escalation level reached (tracked in
critical_ack_attempts).
5. Error Handling
| Scenario | Strategy |
|---|---|
| Order event missing patient reference | Reject with LAB_ORDER_PATIENT_NOT_FOUND; DLQ |
| FHIR publish fails on release | Retry via outbox; release action rolls back until FHIR confirm |
| Duplicate result entry | Idempotency key on (accessionId, testCode, enteredBy, timestamp) |
| Analyzer import parse error | Store raw payload in analyzer_raw_messages; raise LAB_ANALYZER_PARSE_ERROR |
| Terminology lookup unavailable | Warn + proceed with local catalog fallback; flag result terminology_unvalidated=true |