feat(medications): add optional ATC + RxNorm codes to the medication row

Add two nullable, additive columns to `Medication` (`atc_code`,
`rxnorm_code`) so a user or clinician can assert a drug-classification
code that the health-record FHIR export emits on the medication concept.
Codes are taken verbatim, never machine-guessed: a wrong code is a
clinical-safety problem, an absent one is merely a (conformant)
text-only concept.

- Migration 0103 — additive, nullable, no backfill. Pre-existing rows
  read NULL, which the exporter already treats as "no code".
- Validate on write — ATC `^[A-Z]\d{2}[A-Z]{2}\d{2}$`, RxCUI `^\d+$`;
  422 on a malformed value. Wired field-by-field through the create +
  update routes (no mass assignment); `null` clears a code on update.
- Surface both codes in the medication advanced-settings sheet's Data
  group with a self-saving input, and echo them on the GET/POST/PUT
  response shape. OpenAPI regenerated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit 2e0051d42826fa3f043c32e78a34dab7c8050165)
This commit is contained in:
Marc-André Bombeck committed 2026-06-02 16:45:23 +02:00
1 parent eff7b42348
commit 0a8c6e307c
18 files changed
+476

No files matched your search

+77
View File
@@ -2382,6 +2382,22 @@ components:
description: iOS 26 AlarmKit critical-reminder opt-in. Default false. Critical alarms bypass the device mute switch /
Focus; the server stores the preference only and hangs no server-side behaviour off it.
type: boolean
atcCode:
description: Optional WHO ATC classification code (active-substance class, 7 chars, e.g. `A10BX10`).
User/clinician-asserted; never machine-guessed. Emitted on the FHIR `medicationCodeableConcept` under
`http://www.whocc.no/atc`. NULL clears it; absent leaves it untouched.
anyOf:
- type: string
pattern: ^[A-Z]\d{2}[A-Z]{2}\d{2}$
- type: "null"
rxNormCode:
description: Optional RxNorm RxCUI (numeric, US identifier, e.g. `2601723`). Secondary coding emitted under
`http://www.nlm.nih.gov/research/umls/rxnorm` alongside any ATC code, never instead of the free-text name.
NULL clears it; absent leaves it untouched.
anyOf:
- type: string
pattern: ^\d+$
- type: "null"
startsOn:
description: Date the medication course begins (ISO `YYYY-MM-DD`). Anchors RRULE BYDAY / BYMONTHDAY patterns and the
rolling-interval countdown's first window. NULL = active from creation (the legacy implicit behaviour).
@@ -2584,6 +2600,22 @@ components:
description: iOS 26 AlarmKit critical-reminder opt-in. Critical alarms bypass the device mute switch / Focus; the server
stores the preference only.
type: boolean
atcCode:
description: Optional WHO ATC classification code (active-substance class, 7 chars, e.g. `A10BX10`).
User/clinician-asserted; never machine-guessed. Emitted on the FHIR `medicationCodeableConcept` under
`http://www.whocc.no/atc`. NULL clears it; absent leaves it untouched.
anyOf:
- type: string
pattern: ^[A-Z]\d{2}[A-Z]{2}\d{2}$
- type: "null"
rxNormCode:
description: Optional RxNorm RxCUI (numeric, US identifier, e.g. `2601723`). Secondary coding emitted under
`http://www.nlm.nih.gov/research/umls/rxnorm` alongside any ATC code, never instead of the free-text name.
NULL clears it; absent leaves it untouched.
anyOf:
- type: string
pattern: ^\d+$
- type: "null"
startsOn:
description: Date the medication course begins (ISO `YYYY-MM-DD`). Anchors RRULE BYDAY / BYMONTHDAY patterns and the
rolling-interval countdown's first window. NULL = active from creation (the legacy implicit behaviour).
@@ -4189,6 +4221,19 @@ components:
type: boolean
description: v1.7.0 iOS 26 AlarmKit critical-reminder opt-in. Default false. Critical alarms bypass the device mute
switch / Focus; the server stores the preference only.
atcCode:
anyOf:
- type: string
- type: "null"
description: v1.9.0 optional WHO ATC classification code (active-substance class, e.g. `A10BX10`).
User/clinician-asserted; never machine-guessed. Emitted on the FHIR `medicationCodeableConcept` under
`http://www.whocc.no/atc`. NULL = no code captured.
rxNormCode:
anyOf:
- type: string
- type: "null"
description: v1.9.0 optional RxNorm RxCUI (numeric, US identifier, e.g. `2601723`). Secondary FHIR coding under
`http://www.nlm.nih.gov/research/umls/rxnorm`, alongside any ATC code. NULL = no code captured.
pausedAt:
anyOf:
- type: string
@@ -4267,6 +4312,8 @@ components:
- notificationsEnabled
- liveActivityEnabled
- criticalAlarmEnabled
- atcCode
- rxNormCode
- pausedAt
- snoozedUntil
- nextDueAt
@@ -4349,6 +4396,19 @@ components:
type: boolean
description: v1.7.0 iOS 26 AlarmKit critical-reminder opt-in. Default false. Critical alarms bypass the device mute
switch / Focus; the server stores the preference only.
atcCode:
anyOf:
- type: string
- type: "null"
description: v1.9.0 optional WHO ATC classification code (active-substance class, e.g. `A10BX10`).
User/clinician-asserted; never machine-guessed. Emitted on the FHIR `medicationCodeableConcept` under
`http://www.whocc.no/atc`. NULL = no code captured.
rxNormCode:
anyOf:
- type: string
- type: "null"
description: v1.9.0 optional RxNorm RxCUI (numeric, US identifier, e.g. `2601723`). Secondary FHIR coding under
`http://www.nlm.nih.gov/research/umls/rxnorm`, alongside any ATC code. NULL = no code captured.
pausedAt:
anyOf:
- type: string
@@ -4414,6 +4474,8 @@ components:
- notificationsEnabled
- liveActivityEnabled
- criticalAlarmEnabled
- atcCode
- rxNormCode
- pausedAt
- snoozedUntil
- nextDueAt
@@ -6803,6 +6865,19 @@ components:
type: boolean
description: v1.7.0 iOS 26 AlarmKit critical-reminder opt-in. Default false. Critical alarms bypass the device mute
switch / Focus; the server stores the preference only.
atcCode:
anyOf:
- type: string
- type: "null"
description: v1.9.0 optional WHO ATC classification code (active-substance class, e.g. `A10BX10`).
User/clinician-asserted; never machine-guessed. Emitted on the FHIR `medicationCodeableConcept` under
`http://www.whocc.no/atc`. NULL = no code captured.
rxNormCode:
anyOf:
- type: string
- type: "null"
description: v1.9.0 optional RxNorm RxCUI (numeric, US identifier, e.g. `2601723`). Secondary FHIR coding under
`http://www.nlm.nih.gov/research/umls/rxnorm`, alongside any ATC code. NULL = no code captured.
pausedAt:
anyOf:
- type: string
@@ -6866,6 +6941,8 @@ components:
- notificationsEnabled
- liveActivityEnabled
- criticalAlarmEnabled
- atcCode
- rxNormCode
- pausedAt
- snoozedUntil
- nextDueAt