Orders Service — Application Logic
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template
1. Commands
| Command | Use case class | Key steps | Roles |
|---|---|---|---|
CreateOrderCommand | CreateOrderUseCase | Validate patient/encounter, resolve order code, run CDS checks (allergy, drug-drug, duplicate, dosing), persist draft order, emit order.created | CLINICIAN, PRESCRIBER |
ActivateOrderCommand | ActivateOrderUseCase | Check for unacknowledged hard-stops, require acknowledgement for warnings, transition to active, emit order.activated | CLINICIAN, PRESCRIBER |
AcknowledgeCdsAlertCommand | AcknowledgeCdsAlertUseCase | Record clinician acknowledgement with reason on CDS alert; required before activation when warning present | CLINICIAN, PRESCRIBER |
HoldOrderCommand | HoldOrderUseCase | Transition active → on-hold with reason; emit order.on-hold | CLINICIAN |
ResumeOrderCommand | ResumeOrderUseCase | Transition on-hold → active; re-run CDS if medication; emit order.activated | CLINICIAN |
CancelOrderCommand | CancelOrderUseCase | Transition to cancelled (from draft or active); reason required; emit order.cancelled | CLINICIAN, PRESCRIBER, NURSE (own type) |
CompleteOrderCommand | CompleteOrderUseCase | Called by fulfilment service via event; transition to completed; emit order.completed | System (event-driven) |
CorrectOrderCommand | CorrectOrderUseCase | Transition to entered-in-error; audit previous state; emit order.corrected | CLINICIAN, ADMIN |
CreateOrderSetCommand | CreateOrderSetUseCase | Persist OrderSet template with order templates | CLINICIAN, ADMIN |
InstantiateOrderSetCommand | InstantiateOrderSetUseCase | Create one draft Order per template; run CDS batch; return array of order IDs | CLINICIAN, PRESCRIBER |
CreateReferralCommand | CreateReferralUseCase | Create referral order type; validate referral detail; on activation emit referral.created | CLINICIAN |
UpdateReferralStatusCommand | UpdateReferralStatusUseCase | Accept inbound referral acceptance/rejection from receiving facility | CLINICIAN, ADMIN |
2. Queries
| Query | Use case class | Description | Roles |
|---|---|---|---|
GetOrderByIdQuery | GetOrderUseCase | Single order by orderId | CLINICIAN, NURSE, PATIENT (own) |
ListPatientOrdersQuery | ListPatientOrdersUseCase | All orders for a patient; filterable by type, status, date range, encounter | CLINICIAN, NURSE, PATIENT (own) |
ListEncounterOrdersQuery | ListEncounterOrdersUseCase | All orders for a specific encounter | CLINICIAN, NURSE |
GetOrderSetByIdQuery | GetOrderSetUseCase | Single order set template | CLINICIAN |
ListOrderSetsQuery | ListOrderSetsUseCase | All order set templates for tenant; filterable by type, name | CLINICIAN, ADMIN |
GetCdsAlertsForOrderQuery | GetCdsAlertsUseCase | All CDS alerts attached to an order | CLINICIAN |
GetReferralDetailQuery | GetReferralDetailUseCase | Full referral details including tracking status | CLINICIAN, PATIENT (own) |
ListPendingReferralsQuery | ListPendingReferralsUseCase | All active referrals awaiting scheduling | CLINICIAN, ADMIN |
3. Sequence Diagrams
3.1 Create and Activate Medication Order
Clinician → API: POST /v1/orders { orderType: "medication", patientId, encounterId, medicationDetail, ... }
API → CreateOrderUseCase: execute(command)
CreateOrderUseCase → PatientPort: assertPatientActive(patientId)
CreateOrderUseCase → EncounterPort: assertEncounterActive(encounterId)
CreateOrderUseCase → CdsPort: checkAllergy(patientId, medicationCode)
CreateOrderUseCase → CdsPort: checkDrugInteraction(patientId, medicationCode, activeMedications)
CreateOrderUseCase → CdsPort: checkDuplicate(patientId, medicationCode)
CreateOrderUseCase → CdsPort: checkDosing(medicationDetail)
alt hard-stop returned
CreateOrderUseCase → API: persist draft with hard-stop alert; return 201 with cdsAlerts[{level:"hard-stop"}]
end
alt warning returned
CreateOrderUseCase → API: persist draft with warning alert; return 201 with cdsAlerts[{level:"warning"}]
end
CreateOrderUseCase → OrderRepository: save(draft order) [+ outbox entry in transaction]
OutboxRelay → NATS: clinical.orders.{patientId} → order.created
Clinician → API: POST /v1/orders/:id/activate
API → ActivateOrderUseCase: execute
alt unacknowledged hard-stop
ActivateOrderUseCase → API: throw CdsHardStopError (422)
end
alt warning not acknowledged
ActivateOrderUseCase → API: throw CdsWarningUnacknowledgedError (422)
end
ActivateOrderUseCase → OrderRepository: save(active order) [+ outbox]
OutboxRelay → NATS: clinical.orders.{patientId} → order.activated
NATS → pharmacy-service (medication), laboratory-service (lab), etc.
API → Clinician: 200 { status: "active" }
3.2 Referral Creation
Clinician → API: POST /v1/orders { orderType: "referral", referralDetail: { referToFacilityId, specialty, urgency } }
API → CreateReferralUseCase: execute
CreateReferralUseCase → PatientPort: assertPatientActive
CreateReferralUseCase → OrderRepository: save(draft) [+ outbox]
Clinician → API: POST /v1/orders/:id/activate
ActivateOrderUseCase → OrderRepository: save(active) [+ outbox: referral.created]
OutboxRelay → NATS: clinical.orders.{patientId} → referral.created
NATS → scheduling-service: proposed appointment creation
NATS → communication-service: referral notification
3.3 Order Set Instantiation
Clinician → API: POST /v1/order-sets/:setId/instantiate { patientId, encounterId }
API → InstantiateOrderSetUseCase: execute
InstantiateOrderSetUseCase → OrderSetRepository: loadTemplate(setId)
InstantiateOrderSetUseCase → [for each template entry]:
CreateOrderUseCase: execute(derived command)
CDS checks run per order
OrderRepository: save(draft order)
API → Clinician: 201 { orderIds: ["ord_01...", "ord_02...", ...], cdsAlerts: [...] }
4. Ports (Hexagonal Boundaries)
| Port name | Direction | Purpose |
|---|---|---|
OrderRepositoryPort | Outbound | Persist and query Order aggregates |
OrderSetRepositoryPort | Outbound | Persist and query OrderSet templates |
CdsPort | Outbound | Call CDS engine for allergy, interaction, duplicate, dosing checks |
PatientPort | Outbound | Assert patient active/not deceased |
EncounterPort | Outbound | Assert encounter active |
AllergyPort | Outbound | Retrieve patient allergy list for CDS |
OutboxPort | Outbound | Write events to outbox atomically |
EventPublisherPort | Outbound | NATS JetStream publisher (used by outbox relay) |
5. CDS Check Details
| Check | Trigger | Hard-stop or warning |
|---|---|---|
| Allergy check | Medication, procedure orders | Hard-stop if confirmed allergy; warning if intolerance |
| Drug-drug interaction | Medication orders | Hard-stop for contraindicated combinations; warning for monitored combinations |
| Duplicate order check | All order types | Warning if active identical order exists for patient within 24h |
| Dosing range check | Medication orders | Hard-stop if dose exceeds maximum safe dose per weight; warning if above recommended |
6. Error Handling
| Error | HTTP code | Domain code |
|---|---|---|
| Patient not found | 404 | PATIENT_NOT_FOUND |
| Patient deceased | 422 | PATIENT_DECEASED |
| Encounter not found or inactive | 422 | ENCOUNTER_INACTIVE |
| CDS hard-stop blocks activation | 422 | CDS_HARD_STOP |
| CDS warning not acknowledged | 422 | CDS_WARNING_UNACKNOWLEDGED |
| Order in terminal state | 409 | ORDER_TERMINAL_STATE |
| Optimistic lock conflict | 409 | OPTIMISTIC_LOCK_CONFLICT |
| Duplicate mutation | 409 | DUPLICATE_MUTATION |
| Module not entitled | 403 | MODULE_NOT_ENTITLED |