Skip to main content

Orders Service — User Stories

Service: orders-service Story prefix: ORDERS-US Last updated: 2026-04-18

Stories

ORDERS-US-001 — Create medication order with full CDS evaluation

FieldValue
Issue typeStory
SummaryClinician creates a medication order with CDS allergy/DDI checks
Epic linkORDERS-EPIC-01
StatusTo Do
PriorityMust
Story points8
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service, cds-engine
FR referencesFR-ORDERS-001
Legacy FR refsFR-CPOE-001
DependenciesORDERS-US-006 (CDS gate), cross-service: REG-US-001

User story: As a prescriber, when I enter a new medication order during an active patient encounter, I want the system to run allergy and drug interaction checks before saving so that I am alerted to potential patient safety issues before the order is activated.

Acceptance criteria (Gherkin):

  • Given a prescriber has an active encounter for a patient with a known penicillin allergy, when they submit POST /v1/orders with orderType: "medication" and medicationCode: amoxicillin, then the order is saved in draft status and the response includes cdsAlerts[{level: "hard-stop", ruleId: "ALLERGY_PENICILLIN"}].
  • Given a prescriber submits a medication order with no known conflicts, when all CDS checks pass, then the order is created in draft status with empty cdsAlerts[] and HTTP 201.
  • Given a medication order with a drug-drug interaction warning (not hard-stop), when the prescriber submits, then the order is saved in draft with cdsAlerts[{level: "warning"}] and the prescriber can proceed to acknowledge and activate.

Technical notes:

  • POST /v1/orders with orderType: "medication".
  • CDS checks: allergy, drug-drug interaction, duplicate, dosing range — all run synchronously in CreateOrderUseCase.
  • Hard-stop: order saved as draft but ActivateOrderCommand blocked until ADMIN override.
  • Event: clinical.orders.order.created.v1 published via outbox.

Definition of Done:

  • Unit + integration tests added; domain ≥ 95% coverage; CDS guard paths tested.
  • OpenAPI contract updated; Pact consumer tests green.
  • outbox.spec.ts passing.
  • Telemetry spans: orders.create, orders.cds.allergy_check, orders.cds.drug_interaction.
  • Documentation updated.

ORDERS-US-002 — Create laboratory order and route to lab worklist

FieldValue
Issue typeStory
SummaryClinician creates lab order that appears in laboratory-service worklist
Epic linkORDERS-EPIC-03
StatusTo Do
PriorityMust
Story points5
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service, laboratory-service, NATS
FR referencesFR-ORDERS-009
Legacy FR refsFR-REQ-001, FR-CPOE-006
DependenciesORDERS-US-001, cross-service: LAB-US-001

User story: As a clinician, when I activate a laboratory order, I want it to automatically appear in the laboratory service worklist so that lab technicians can process it without any manual re-entry.

Acceptance criteria (Gherkin):

  • Given a clinician has a draft lab order in active status, when POST /v1/orders/:id/activate succeeds, then clinical.orders.order.activated.v1 event is published to NATS with orderType: "laboratory".
  • Given the event is published, when laboratory-service consumes it, then the order appears in the lab worklist within 30 seconds.
  • Given NATS is temporarily unavailable at activation, when NATS recovers, then the outbox relay delivers the event and the lab worklist is updated (eventual consistency within SLA).

Technical notes:

  • Activation: POST /v1/orders/:id/activate.
  • NATS subject: clinical.orders.{patientId}.
  • Event: clinical.orders.order.activated.v1 — consumed by laboratory-service consumer group.
  • Outbox pattern: event written transactionally with order state change.

Definition of Done:

  • outbox.spec.ts green; NATS event verified in integration test.
  • Pact contract: clinical.orders.order.activated.v1 verified against laboratory-service consumer.
  • Coverage ≥ 80%.

ORDERS-US-003 — Activate order with CDS warning acknowledgement

FieldValue
Issue typeStory
SummaryPrescriber acknowledges CDS warning before activating medication order
Epic linkORDERS-EPIC-02
StatusTo Do
PriorityMust
Story points5
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service, cds-engine
FR referencesFR-ORDERS-007
Legacy FR refsFR-CPOE-005
DependenciesORDERS-US-001

User story: As a prescriber, when I have a medication order with a CDS warning (drug interaction), I want to acknowledge the warning with a clinical reason before activating the order so that my override is documented for audit purposes.

Acceptance criteria (Gherkin):

  • Given a draft medication order has a CDS warning alert, when the prescriber calls POST /v1/orders/:alertId/acknowledge with reason: "Benefit outweighs risk; monitoring plan in place", then the alert is marked acknowledged and the order can proceed to activation.
  • Given a CDS warning has not been acknowledged, when the prescriber calls POST /v1/orders/:id/activate, then the response is 422 with CDS_WARNING_UNACKNOWLEDGED.
  • Given a CDS hard-stop alert, when a CLINICIAN attempts to acknowledge, then 403 is returned — only ADMIN can acknowledge hard-stops.

Technical notes:

  • POST /v1/orders/:orderId/cds-alerts/:alertId/acknowledge with body { reason: string }.
  • Acknowledgement stored immutably in orders.cds_alerts.acknowledged_at, acknowledged_by, acknowledgement_reason.
  • Audit event: CDS_WARNING_ACKNOWLEDGED with actor, reason, rule ID.

Definition of Done:

  • Immutability of acknowledgement record tested.
  • Audit log integration test verifying record stored.
  • OpenAPI schema updated.

ORDERS-US-004 — Cancel an active order

FieldValue
Issue typeStory
SummaryClinician cancels an active order with documented reason
Epic linkORDERS-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service
FR referencesFR-ORDERS-004
Legacy FR refsFR-CPOE-003
DependenciesORDERS-US-001

User story: As a clinician, when I need to stop an active order (wrong medication, clinical decision change), I want to cancel it with a documented reason so that downstream services stop processing it and the reason is visible in the patient record.

Acceptance criteria (Gherkin):

  • Given an active order, when the clinician calls DELETE /v1/orders/:id with body { reason: "Patient allergic — new allergy identified" }, then the order transitions to cancelled, order.cancelled event is emitted, and 200 is returned.
  • Given a completed order, when a clinician attempts cancellation, then 409 ORDER_TERMINAL_STATE is returned.
  • Given a NURSE role cancelling an order they did not create, when the order is a nursing order, then cancellation succeeds. For other order types, 403 is returned.

Technical notes:

  • DELETE /v1/orders/:id with JSON body { cancelReason: string }.
  • Terminal state guard: completed and entered-in-error cannot be cancelled.
  • Event: clinical.orders.order.cancelled.v1.

Definition of Done:

  • State machine terminal guard unit tests.
  • Role-based cancel permission integration test.
  • Pact: order.cancelled.v1 verified against downstream consumers.

ORDERS-US-005 — View all orders for a patient encounter

FieldValue
Issue typeStory
SummaryClinician views all orders for a specific encounter
Epic linkORDERS-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service
FR referencesFR-ORDERS-005
Legacy FR refsFR-CPOE-002
DependenciesORDERS-US-001

User story: As a clinician, when I open a patient encounter in the EHR, I want to see all orders associated with that encounter grouped by type and status so that I have a complete view of the current care plan.

Acceptance criteria (Gherkin):

  • Given an encounter with 5 orders of mixed types, when GET /v1/orders?encounterId=enc_01J... is called, then all 5 orders are returned with correct type, status, and priority.
  • Given a request with no encounterId or patientId, when the query is submitted, then 400 MISSING_REQUIRED_FILTER is returned.
  • Given a NURSE role querying orders for an encounter, when the encounter belongs to a different tenant, then 0 results (RLS enforced, not 403).

Technical notes:

  • GET /v1/orders?encounterId=&type=&status=&cursor= — cursor pagination.
  • Filterable by orderType, status, priority, date range.
  • RLS enforces tenant isolation; no cross-tenant rows returned.

Definition of Done:

  • tenant-isolation.spec.ts covers this query path.
  • Cursor pagination tested with > 100 records.

ORDERS-US-006 — CDS hard-stop blocks medication order activation

FieldValue
Issue typeStory
SummaryMedication order with confirmed allergy cannot be activated without ADMIN override
Epic linkORDERS-EPIC-02
StatusTo Do
PriorityMust
Story points8
Labelsservice:orders, type:backend, slice:S1, type:patient-safety
Componentsorders-service, cds-engine
FR referencesFR-ORDERS-006
Legacy FR refsFR-CPOE-004
DependenciesORDERS-US-001

User story: As a platform safety system, when a clinician tries to activate a medication order that triggers a CDS hard-stop (confirmed allergy), I want to block activation until an ADMIN provides a documented clinical override reason so that patient safety is enforced at every order entry point.

Acceptance criteria (Gherkin):

  • Given an order with an unacknowledged hard-stop CDS alert, when any role calls POST /v1/orders/:id/activate, then 422 CDS_HARD_STOP is returned and order remains draft.
  • Given an ADMIN acknowledges the hard-stop with a clinical reason, when POST /v1/orders/:id/activate is called, then the order transitions to active and the override is logged immutably.
  • Given CDS engine is unavailable, when a medication order is submitted, then CDS_DEGRADED soft alert is recorded and medication activation is blocked until CDS recovers (unless ADMIN overrides with CDS_DEGRADED_OVERRIDE).

Technical notes:

  • Hard-stop acknowledgement: ADMIN role only (POST /v1/orders/:orderId/cds-alerts/:alertId/acknowledge).
  • Audit event: CDS_HARD_STOP_BLOCKED, CDS_HARD_STOP_ADMIN_OVERRIDE.
  • 7-year immutable retention on all CDS override records.

Definition of Done:

  • CDS degraded mode tested in integration.
  • ADMIN-only gate for hard-stop tested.
  • 7-year retention policy documented in DATA_MODEL.md.

ORDERS-US-007 — Duplicate order detection

FieldValue
Issue typeStory
SummarySystem warns when identical order already active within 24 hours
Epic linkORDERS-EPIC-02
StatusTo Do
PriorityMust
Story points5
Labelsservice:orders, type:backend, slice:S1, type:patient-safety
Componentsorders-service, cds-engine
FR referencesFR-ORDERS-008
Legacy FR refsFR-CPOE-005
DependenciesORDERS-US-001

User story: As a prescriber, when I attempt to create an order that is identical to one already active for the same patient within 24 hours, I want to receive a duplicate order CDS warning so that I can intentionally confirm or cancel the redundant order.

Acceptance criteria (Gherkin):

  • Given a patient has an active amoxicillin order, when a prescriber creates a new amoxicillin order for the same patient and encounter, then a warning CDS alert with ruleId: "DUPLICATE_ORDER_24H" is returned.
  • Given the duplicate warning is shown, when the prescriber acknowledges it with a reason, then the order can proceed to activation.
  • Given two orders with different drug codes (amoxicillin vs azithromycin), when a new order is created, then no duplicate CDS alert fires.

Technical notes:

  • Duplicate check: same orderCode.code + orderType + active status within 24 h for same patientId.
  • CDS rule: DUPLICATE_ORDER_24H, severity: warning.
  • Idempotency check (client_mutation_id DB constraint) is separate from CDS duplicate check.

Definition of Done:

  • Unit tests for duplicate detection boundary conditions.
  • Integration test: duplicate warning fires; acknowledgement allows activation.

ORDERS-US-008 — Create radiology order and route to radiology service

FieldValue
Issue typeStory
SummaryClinician creates radiology order routed to radiology-service worklist
Epic linkORDERS-EPIC-03
StatusTo Do
PriorityMust
Story points5
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service, radiology-service, NATS
FR referencesFR-ORDERS-010
Legacy FR refsFR-REQ-002
DependenciesORDERS-US-001, cross-service: RAD-US-001

User story: As a clinician, when I activate a radiology order (X-ray, CT, MRI), I want the imaging request to appear immediately in the radiology worklist so that radiographers can schedule and perform the study without manual transcription.

Acceptance criteria (Gherkin):

  • Given a draft radiology order with orderType: "radiology" and radiologyDetail: { modality: "CT", region: "Chest", contrastRequired: true }, when activated, then clinical.orders.order.activated.v1 is published with full radiologyDetail payload.
  • Given the event is consumed by radiology-service, when it creates a worklist entry, then the modality, region, laterality, and contrast fields are correctly mapped.
  • Given a radiology order without a radiologyDetail block, when submitted, then 400 MISSING_DETAIL_FOR_ORDER_TYPE is returned.

Technical notes:

  • radiologyDetail required for orderType: "radiology".
  • FHIR mapping: ServiceRequest with category: [{"code":"imaging"}].
  • Pact: clinical.orders.order.activated.v1 verified against radiology-service consumer.

Definition of Done:

  • Validation of required detail block per order type tested.
  • Pact contract test passing.

ORDERS-US-009 — Create and track internal referral

FieldValue
Issue typeStory
SummaryClinician creates internal referral with scheduling coordination
Epic linkORDERS-EPIC-04
StatusTo Do
PriorityMust
Story points8
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service, scheduling-service, communication-service
FR referencesFR-ORDERS-020
Legacy FR refsFR-REF-001
DependenciesORDERS-US-001, cross-service: SCHED-US-001, COMMS-US-001

User story: As a clinician, when I need to refer a patient to a specialist within our facility network, I want to create a referral order that automatically triggers the scheduling team to arrange the appointment so that the patient does not fall through the cracks of a manual referral process.

Acceptance criteria (Gherkin):

  • Given a clinician creates a referral order with referralType: "internal", referToSpecialty: "cardiology", urgency: "routine", when activated, then clinical.orders.referral.created.v1 is published.
  • Given the event is consumed by scheduling-service, when it creates an appointment proposal, then the referral status in orders-service transitions to pending_scheduling.
  • Given a referral is pending scheduling for > 72 hours, when no scheduling event is received, then the OrdersReferralOverdue Prometheus alert fires.

Technical notes:

  • POST /v1/orders with orderType: "referral", referralDetail required.
  • clinical.orders.referral.created.v1 consumed by scheduling-service and communication-service.
  • Referral status updates received via SCHEDULING.appointment.fulfilled.v1 event.

Definition of Done:

  • Referral overdue alert configured with 72 h threshold.
  • referral.created.v1 Pact contract test against scheduling-service consumer.
  • Referral status update via event integration test.

ORDERS-US-010 — Instantiate order set for patient

FieldValue
Issue typeStory
SummaryClinician applies an order set template creating multiple draft orders at once
Epic linkORDERS-EPIC-05
StatusTo Do
PriorityShould
Story points8
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service
FR referencesFR-ORDERS-030
Legacy FR refsFR-CPOE-010
DependenciesORDERS-US-001

User story: As a clinician, when I need to order a standard clinical protocol (e.g., pre-operative blood work), I want to apply an order set template to the patient with one action so that all required orders are created in draft simultaneously and I can review CDS alerts before activating each one.

Acceptance criteria (Gherkin):

  • Given an order set template ords_01J... with 3 order entries (CBC, metabolic panel, coagulation screen), when POST /v1/order-sets/:id/instantiate is called with patientId and encounterId, then 3 draft orders are returned in the response.
  • Given one order entry triggers a CDS warning, when instantiation completes, then the response includes cdsAlerts on that specific order and successCount: 2, warningCount: 1.
  • Given one order entry fails to create (e.g., encounter inactive), when instantiation is called, then the response shows failedTemplates: [{templateId, reason}] and successfully created orders are persisted.

Technical notes:

  • POST /v1/order-sets/:id/instantiate — body: { patientId, encounterId, overrides? }.
  • Each order created in independent transaction.
  • Partial failure: failedTemplates[] in response; already-created orders persisted.

Definition of Done:

  • Partial failure scenario tested (some orders created, some failed).
  • ORDER_SET_PARTIAL_FAILURE audit event tested.

ORDERS-US-011 — Read order as FHIR ServiceRequest

FieldValue
Issue typeStory
SummaryExternal FHIR client reads order as FHIR R4 ServiceRequest
Epic linkORDERS-EPIC-06
StatusTo Do
PriorityShould
Story points5
Labelsservice:orders, type:backend, type:api, slice:S1
Componentsorders-service, interop-service
FR referencesFR-ORDERS-040
Legacy FR refsFR-CPOE-020
DependenciesORDERS-US-001, cross-service: INTEROP-US-001

User story: As a national HMIS system or partner EMR, when I query the FHIR endpoint for a patient's orders, I want to receive them as FHIR R4 ServiceRequest and MedicationRequest resources so that I can integrate without platform-specific APIs.

Acceptance criteria (Gherkin):

  • Given an active lab order ord_01J... exists, when GET /fhir/R4/ServiceRequest/ord_01J... is called via interop-service, then a valid FHIR R4 ServiceRequest is returned with correct status, category, code, and subject fields.
  • Given a FHIR search GET /fhir/R4/ServiceRequest?patient=Patient/pat_01J..., when executed, then a Bundle of type searchset is returned with all non-entered-in-error orders for the patient.
  • Given an invalid FHIR resource ID, when read is attempted, then FHIR OperationOutcome with not-found issue is returned.

Technical notes:

  • Internal FHIR surface: GET /internal/fhir/ServiceRequest/:id — proxied by interop-service from external /fhir/R4/.
  • Mapping: OrderServiceRequest; medicationDetailMedicationRequest.
  • US Core ServiceRequest profile validation in contract tests.

Definition of Done:

  • FHIR profile conformance test green (test/contract/serviceRequest.fhir.schema.spec.ts).
  • OperationOutcome tested for not-found and auth denial.

ORDERS-US-012 — Migrate legacy CPOE orders to unified schema

FieldValue
Issue typeStory
SummaryHistorical CPOE orders migrated to orders-service with validated record counts
Epic linkORDERS-EPIC-07
StatusTo Do
PriorityMust
Story points13
Labelsservice:orders, type:backend, slice:S0
Componentsorders-service, migration-scripts
FR referencesFR-ORDERS-050
Legacy FR refsFR-CPOE-030
DependenciesORDERS-EPIC-01

User story: As a platform migration engineer, when I run the CPOE migration scripts, I want all historical orders to be present in the new orders-service with zero data loss so that clinicians see a continuous order history after cut-over.

Acceptance criteria (Gherkin):

  • Given legacy CPOE has 50,000 order records, when the migration script runs to completion, then the validation script reports 50,000 migrated records with 0 discrepancy.
  • Given the migration script runs twice (idempotency), when it completes the second run, then the count remains 50,000 with no duplicates (upsert behaviour verified).
  • Given a legacy order has no encounterId, when migrated, then it is assigned to a synthetic encounter and flagged with migration_no_encounter: true for clinical review.

Technical notes:

  • Migration scripts: scripts/migrate-cpoe-orders.ts, scripts/migrate-lab-requisitions.ts.
  • Idempotent via upsert on id.
  • 10% sample clinical validation required before go-live.

Definition of Done:

  • Migration scripts committed and reviewed.
  • Validation script report documented.
  • Rollback plan tested in staging.