Skip to main content

Medication Service — User Stories

Service: medication-service Story prefix: MED-US Last updated: 2026-04-17

Stories

MED-US-001 — Draft a prescription

FieldValue
Issue typeStory
SummaryPrescriber drafts a prescription with structured sig
Epic linkMED-EPIC-01
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S1
Componentsprescription, api
FR referencesFR-MED-010
Legacy FR refsFR-MEDS-010
Dependencies

User story: As a prescriber, when I start writing a medication order, I want to draft with structured dose/route/frequency so that downstream systems can parse it reliably.

Acceptance criteria:

  • Given authenticated prescriber with medication:prescribe, when POST /api/v1/medications, then 201 with id, status draft.
  • Given invalid UCUM unit, when posting sig, then 400 with validation error.
  • Given code from terminology-service, when draft saved, then medicationCode and medicationDisplay stored together.

Technical notes:

  • Use DraftPrescriptionUseCase; validates against Sig VO.
  • Calls TerminologyService.lookup for medication display.

Definition of Done:

  • Unit + integration tests added; coverage ≥ thresholds.
  • OpenAPI updated; Pact consumer tests green.
  • Telemetry spans added.

MED-US-002 — Sign a prescription with safety checks

FieldValue
Issue typeStory
SummarySign prescription runs allergy/interaction checks, blocks on critical alerts
Epic linkMED-EPIC-02
StatusTo Do
PriorityMust
Story points8
Labelsservice:medication-service, type:backend, slice:S1
Componentsprescription, safety-check
FR referencesFR-MED-011, FR-MED-030..032
Legacy FR refsFR-MEDS-030..032, BR-MEDS-001
DependenciesMED-US-001

User story: As a prescriber, when I sign a prescription, I want safety checks to run automatically so that I cannot inadvertently prescribe a medication that would harm the patient.

Acceptance criteria:

  • Given patient has penicillin allergy, when prescribing amoxicillin and signing, then 422 MED_ALERT_BLOCKING with alert array.
  • Given override with ≥10-char reason, when signing with overrides, then 201 + medication.alert.overridden.v1 event + medication.prescription.signed.v1 event.
  • Given drug-KB timeout, when signing, then 503 — sign refused.

Technical notes:

  • SignPrescriptionUseCase fetches AllergyIntolerance + Condition via FhirClient.
  • Captures drugKbVersion in override record.

Definition of Done: tests, OpenAPI, Pact, event schema conformance.


MED-US-003 — Discontinue / hold / resume

FieldValue
Issue typeStory
SummaryPrescriber changes prescription lifecycle state
Epic linkMED-EPIC-01
StatusTo Do
PriorityMust
Story points3
Labelsservice:medication-service, type:backend, slice:S1
Componentsprescription
FR referencesFR-MED-012
Legacy FR refsFR-MEDS-001 (discontinued)
DependenciesMED-US-002

User story: As a prescriber, when clinical context changes, I want to discontinue, hold, or resume a prescription with a reason so that the medication list reflects current intent.

Acceptance criteria:

  • Given active prescription, when PUT /discontinue with reason, then status discontinued and medication.prescription.discontinued.v1 emitted.
  • Given on-hold prescription, when PUT /resume, then status active.
  • Given stale ETag, when PUT, then 412.

Technical notes:

  • State machine enforced in aggregate; discontinuing terminal.

Definition of Done: tests, OpenAPI, event schema.


MED-US-004 — Renewal and refill

FieldValue
Issue typeStory
SummarySupport renewal and refill per policy
Epic linkMED-EPIC-01
StatusTo Do
PriorityShould
Story points5
Labelsservice:medication-service, type:backend, slice:S1
Componentsprescription, refill
FR referencesFR-MED-011
Legacy FR refsFR-MEDS-011, BR-PHARM-008
DependenciesMED-US-002

User story: As a prescriber, when authorized, I want to add refills or renew a prescription so patients can continue therapy without re-drafting.

Acceptance criteria:

  • Given active prescription with refillsAuthorized < regulatory max, when POST /refill, then increments refillsAuthorized.
  • Given controlled substance Schedule II, when attempting refill, then 403 (no refills on Schedule II per policy).

Technical notes: policy engine checks controlled schedule.

Definition of Done: tests, OpenAPI, audit event.


MED-US-010 — Allergy + drug-drug interaction check

FieldValue
Issue typeStory
SummaryCall drug KB for cross-checks before sign
Epic linkMED-EPIC-02
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S1
Componentssafety-check, drug-kb
FR referencesFR-MED-030..031
Legacy FR refsFR-MEDS-030..031
Dependencies

User story: As a prescriber, before signing, I want drug-drug and drug-allergy checks run automatically so that I do not need to remember every interaction.

Acceptance criteria: KB call occurs, results returned with severity; high-severity alerts block sign; KB version captured.

Definition of Done: unit tests across matrix; p95 < 700ms.


MED-US-011 — Override alert with reason

FieldValue
Issue typeStory
SummaryRecord override reason + KB snapshot
Epic linkMED-EPIC-02
StatusTo Do
PriorityMust
Story points3
Labelsservice:medication-service, type:backend, slice:S1
Componentsoverride, audit
FR referencesFR-MED-032
Legacy FR refsFR-MEDS-032, FR-PHARM-023
DependenciesMED-US-010

User story: As a prescriber or pharmacist, when I intentionally override a safety alert, I want to record a reason so the decision is auditable.

Acceptance criteria: reason ≥10 chars enforced server-side; override event emitted; DetectedIssue filed.

Definition of Done: tests, event schema.


MED-US-012 — Alert-override governance view

FieldValue
Issue typeStory
SummaryGovernance dashboard of override rates
Epic linkMED-EPIC-02
StatusTo Do
PriorityShould
Story points3
Labelsservice:medication-service, type:analytics, slice:S2
Componentsanalytics, observability
FR referencesFR-MED-032 (governance)
Legacy FR refs
DependenciesMED-US-011

User story: As clinical governance, when reviewing alert fatigue, I want an override rate dashboard so I can tune rules.

Acceptance criteria: Grafana panel exists; rate aggregated by alert type and prescriber role.

Definition of Done: dashboard JSON committed; rule-tuning cadence documented.


MED-US-020 — Start reconciliation session

FieldValue
Issue typeStory
SummaryStart reconciliation at admission / discharge / transfer
Epic linkMED-EPIC-03
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S1
Componentsreconciliation
FR referencesFR-MED-020
Legacy FR refsFR-MEDS-020
DependenciesREG-US-004 (encounter)

User story: As a prescriber, when a patient transitions care, I want a reconciliation session so I can review and reconcile medications.

Acceptance criteria: session created with type; diff loaded.

Definition of Done: unit + integration tests.


MED-US-021 — Act on reconciliation line items

FieldValue
Issue typeStory
SummaryContinue / Discontinue / Modify each line
Epic linkMED-EPIC-03
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S1
Componentsreconciliation
FR referencesFR-MED-021
Legacy FR refsFR-MEDS-021, BR-MEDS-002
DependenciesMED-US-020

User story: As a prescriber, when reviewing reconciliation, I want per-line actions so the outcome is unambiguous.

Acceptance criteria: action recorded with actor + timestamp; completion freezes decisions.

Definition of Done: tests, event on complete.


MED-US-022 — Record MAR event

FieldValue
Issue typeStory
SummaryNurse records given/held/refused
Epic linkMED-EPIC-03
StatusTo Do
PriorityMust
Story points3
Labelsservice:medication-service, type:backend, slice:S1
Componentsmar
FR referencesFR-MED-022
Legacy FR refsFR-MEDS-001 (administration)
DependenciesMED-US-002

User story: As a nurse, when I administer or hold a medication, I want to record it so the clinical team has an accurate MAR.

Acceptance criteria: immutable entry; corrections linked to prior.

Definition of Done: tests, event schema, FHIR MedicationAdministration.


MED-US-030 — Ingest gateway MedicationRequest

FieldValue
Issue typeStory
SummaryConsumer upserts prescription from gateway event
Epic linkMED-EPIC-04
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:worker, slice:S2
Componentsfulfillment, ingestion
FR referencesFR-MED-040
Legacy FR refsFR-PHARM-009
DependenciesEPRX-US-001

User story: As a pharmacy system, when a prescription arrives via the gateway, I want it in my queue within 5s so I can begin fulfillment.

Acceptance criteria: idempotent upsert by gateway_medication_request_fhir_id; consumer lag p95 ≤ 5s.

Definition of Done: inbox test, Pact consumer test.


MED-US-031 — Dispense with inventory decrement

FieldValue
Issue typeStory
SummaryPharmacist completes dispense; atomic decrement
Epic linkMED-EPIC-04
StatusTo Do
PriorityMust
Story points8
Labelsservice:medication-service, type:backend, slice:S2
Componentsdispense, inventory
FR referencesFR-MED-060..062
Legacy FR refsFR-PHARM-042, BR-PHARM-004
DependenciesMED-US-030

User story: As a pharmacist, when I dispense medication, I want inventory to decrement atomically so stock counts stay accurate.

Acceptance criteria: single DB transaction; idempotency key prevents double-dispense; expired/recalled lot blocked; post to gateway on success.

Definition of Done: integration test for atomicity; chaos test for NATS partition.


MED-US-032 — Partial dispense + return

FieldValue
Issue typeStory
SummaryPartial fulfillment and returns/undispense
Epic linkMED-EPIC-04
StatusTo Do
PriorityShould
Story points5
Labelsservice:medication-service, type:backend, slice:S2
Componentsdispense
FR referencesFR-MED-063..064
Legacy FR refsFR-PHARM-043..044
DependenciesMED-US-031

User story: As a pharmacist, when only partial stock is available, I want partial-dispense; and I want to record returns.

Acceptance criteria: status partially-dispensed; return creates inventory credit with reason.

Definition of Done: tests, events.


MED-US-033 — Post MedicationDispense to gateway

FieldValue
Issue typeStory
SummaryPublish dispense to national interop gateway
Epic linkMED-EPIC-04
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S2
Componentsgateway, outbox
FR referencesFR-MED-040
Legacy FR refsFR-PHARM-009
DependenciesMED-US-031, EPRX-US-011

User story: As an integration flow, when dispense completes locally, I want it posted to the gateway so the interop record is complete.

Acceptance criteria: outbox publish; retries with DLQ; pact against gateway.

Definition of Done: pact test, DLQ metric.


MED-US-040 — Receive stock (GRN)

FieldValue
Issue typeStory
SummaryPharmacy technician receives stock with lot/expiry
Epic linkMED-EPIC-05
StatusTo Do
PriorityMust
Story points3
Labelsservice:medication-service, type:backend, slice:S2
Componentsinventory, grn
FR referencesFR-MED-070..071
Legacy FR refsFR-PHARM-050..051
Dependencies

User story: As a pharmacy technician, when new stock arrives, I want to record lot and expiry so dispensing honors them.

Acceptance criteria: creates stock item; emits medication.inventory.stock_received.v1.

Definition of Done: tests.


MED-US-041 — Reorder and expiry alerts

FieldValue
Issue typeStory
SummaryAlerts when stock low or expiry approaching
Epic linkMED-EPIC-05
StatusTo Do
PriorityMust
Story points3
Labelsservice:medication-service, type:worker, slice:S2
Componentsinventory, alerts
FR referencesFR-MED-073..074
Legacy FR refsFR-PHARM-053..054
DependenciesMED-US-040

User story: As a pharmacist, when stock is low or expiring, I want an alert so I can act before stock-out or waste.

Acceptance criteria: scheduled job emits alerts; dedup per day per lot.

Definition of Done: tests, scheduling documented.


MED-US-042 — Recall blocks dispense

FieldValue
Issue typeStory
SummaryMark lot recalled; dispense hard-blocks
Epic linkMED-EPIC-05
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S2
Componentsinventory, recall
FR referencesFR-MED-075
Legacy FR refsFR-PHARM-055
DependenciesMED-US-040

User story: As a pharmacist-in-charge, when a lot is recalled, I want dispense blocked so no patient receives recalled product.

Acceptance criteria: dispense attempt against recalled lot returns 409 LOT_UNAVAILABLE; DetectedIssue emitted.

Definition of Done: tests, audit event.


MED-US-050 — Counter-sign for Schedule II dispense

FieldValue
Issue typeStory
SummarySecond pharmacist counter-signs Schedule II dispense
Epic linkMED-EPIC-06
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S3
Componentscontrolled-substance, dispense
FR referencesFR-MED-050
Legacy FR refsFR-PHARM-033, BR-PHARM-005
DependenciesMED-US-031

User story: As a regulator, when Schedule II is dispensed, I want a distinct counter-sign so chain-of-custody is clear.

Acceptance criteria: counter-sign actor ≠ dispenser; dispense without counter-sign returns 403 COUNTER_SIGN_REQUIRED.

Definition of Done: tests, enhanced audit event.


MED-US-051 — Step-up MFA for controlled-substance prescribe

FieldValue
Issue typeStory
SummaryRequire MFA step-up for CS prescription sign
Epic linkMED-EPIC-06
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:backend, slice:S3
Componentscontrolled-substance, identity
FR referencesFR-MED-051
Legacy FR refsBR-PHARM-003
DependenciesIDENT-US-040

User story: As a prescriber, when signing a Schedule II order, I want a fresh MFA challenge so only I can sign.

Acceptance criteria: JWT amr must include recent MFA factor; else 403.

Definition of Done: tests, identity integration.


MED-US-052 — Disclosure-accounting export

FieldValue
Issue typeStory
SummaryExport CS disclosure-accounting ledger per regulator format
Epic linkMED-EPIC-06
StatusTo Do
PriorityShould
Story points5
Labelsservice:medication-service, type:export, slice:S3
Componentscontrolled-substance, compliance
FR referencesFR-MED-091..092
Legacy FR refsFR-PHARM-072
DependenciesMED-US-050

User story: As a compliance officer, when regulators request a disclosure-accounting, I want a one-click export so I can respond within the required window.

Acceptance criteria: async job; file signed; retention respected.

Definition of Done: tests; sample MoPH export verified.


MED-US-060 — Pharmacy portal offline queue

FieldValue
Issue typeStory
SummaryPortal accepts dispense actions offline for 4h+
Epic linkMED-EPIC-07
StatusTo Do
PriorityShould
Story points8
Labelsservice:medication-service, type:ui, slice:S3
Componentsportal, offline
FR referencesFR-MED-081
Legacy FR refsFR-PHARM-061, NFR-PHARM-005
DependenciesIDENT-US-020

User story: As a pharmacist in a low-connectivity site, when internet fails, I want to continue dispensing so care does not halt.

Acceptance criteria: offline queue retains 4h; idempotency prevents duplicate on sync; banner at 3h.

Definition of Done: E2E offline test.


MED-US-061 — Label printing

FieldValue
Issue typeStory
SummaryPrint prescription + dispense labels directly
Epic linkMED-EPIC-07
StatusTo Do
PriorityShould
Story points3
Labelsservice:medication-service, type:ui, slice:S3
Componentsportal, label
FR referencesFR-MED-084
Legacy FR refsFR-PHARM-064
DependenciesMED-US-031

User story: As a pharmacist, when I dispense, I want to print a label so the patient receives correct directions.

Acceptance criteria: PDF generated <4s p95; RTL/LTR rendered correctly.

Definition of Done: tests.


MED-US-062 — Device binding for portal

FieldValue
Issue typeStory
SummaryBind portal device for offline PHI encryption
Epic linkMED-EPIC-07
StatusTo Do
PriorityMust
Story points5
Labelsservice:medication-service, type:security, slice:S3
Componentsportal, identity
FR referencesFR-MED-082
Legacy FR refsFR-PHARM-063
DependenciesIDENT-US-030

User story: As a security officer, when portals go offline, I want device-bound encryption so PHI is protected on stolen devices.

Acceptance criteria: device key provisioned; cache encrypted at rest; revocation within 5 min online.

Definition of Done: security test.


MED-US-070 — NCPDP SCRIPT adapter (optional)

FieldValue
Issue typeStory
SummaryOptional NCPDP NewRx / CancelRx adapter
Epic linkMED-EPIC-08
StatusTo Do
PriorityCould
Story points8
Labelsservice:medication-service, type:integration, slice:S4
Componentsncpdp
FR referencesFR-MED-041
Legacy FR refsFR-PHARM-010, BR-PHARM-010
DependenciesINTEROP-US-020

User story: As a retail pharmacy partner using NCPDP, when I receive a prescription, I want NewRx over SCRIPT so legacy integration works.

Acceptance criteria: NewRx sent; retry with DLQ; prescriber notified on final failure.

Definition of Done: adapter tests with fixture messages.


MED-US-071 — HL7 v2 RDE / RDS for legacy pharmacies

FieldValue
Issue typeStory
SummaryHL7 v2 adapter via hl7v2-interop
Epic linkMED-EPIC-08
StatusTo Do
PriorityCould
Story points5
Labelsservice:medication-service, type:integration, slice:S4
Componentshl7v2
FR referencesFR-MED-042
Legacy FR refs
DependenciesINTEROP-US-030

User story: As a legacy hospital pharmacy system operator, when new orders are placed, I want RDE^O11 messages so I can integrate without FHIR uplift.

Acceptance criteria: message generated + routed; RDS^O13 ack consumed back.

Definition of Done: integration tests.