From e893a43005ddefcdd880d7b3e1e62d3445260361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Tue, 2 Jun 2026 22:21:26 +0200 Subject: [PATCH] feat(fhir): wire the German BfArM ATC locale toggle into the export route The builder already accepts a germanAtc option that appends the BfArM ATC URI after the WHO entry. Thread it from the health-record export route: an explicit germanAtc flag on the selection payload wins, otherwise it derives from a German-region locale. The WHO coding stays coding[0], byte-identical and locale-independent, so a WHO-only consumer is unaffected. Add the optional germanAtc field to the strict export selection schema and regenerate the OpenAPI contract. --- docs/api/openapi.yaml | 2 ++ src/app/api/export/health-record/route.ts | 18 ++++++++++++++++-- src/lib/validations/health-record-export.ts | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index 7fdd80ece..bc8cb5bbd 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -148,6 +148,8 @@ paths: type: boolean includeAiSummary: type: boolean + germanAtc: + type: boolean required: - format additionalProperties: false diff --git a/src/app/api/export/health-record/route.ts b/src/app/api/export/health-record/route.ts index 842845a11..b8f14a602 100644 --- a/src/app/api/export/health-record/route.ts +++ b/src/app/api/export/health-record/route.ts @@ -90,6 +90,10 @@ export const POST = apiHandler(async (request: NextRequest) => { request.headers.get("accept-language") ?? "", ); + // BfArM ATC: an explicit selection flag wins; otherwise derive it from a + // German-region locale. The WHO ATC coding is unaffected either way. + const germanAtc = selection.germanAtc ?? locale === "de"; + const [data, userTz, userRow] = await Promise.all([ collectDoctorReportData(user.id, range, { practiceName, sections }), resolveUserTimezone(user.id), @@ -136,7 +140,12 @@ export const POST = apiHandler(async (request: NextRequest) => { }); if (selection.format === "fhir") { - const bundle = buildFhirDocumentBundle(data, { insuranceNumber }); + const bundle = buildFhirDocumentBundle( + data, + { insuranceNumber }, + undefined, + { germanAtc }, + ); const json = JSON.stringify(bundle); annotate({ meta: { format: "fhir", bytes: json.length, days: range.days }, @@ -178,7 +187,12 @@ export const POST = apiHandler(async (request: NextRequest) => { } // format === "package": one zip holding the PDF + FHIR Bundle + a README. - const bundle = buildFhirDocumentBundle(data, { insuranceNumber }); + const bundle = buildFhirDocumentBundle( + data, + { insuranceNumber }, + undefined, + { germanAtc }, + ); const readme = t("doctorReport.packageReadme"); const zipped = zipSync( { diff --git a/src/lib/validations/health-record-export.ts b/src/lib/validations/health-record-export.ts index 4afe72394..ca76980fa 100644 --- a/src/lib/validations/health-record-export.ts +++ b/src/lib/validations/health-record-export.ts @@ -97,6 +97,10 @@ export const exportSelectionSchema = z practiceName: z.string().max(120).optional(), includeCharts: z.boolean().optional(), includeAiSummary: z.boolean().optional(), + // FHIR only: additionally emit the German BfArM ATC URI alongside the WHO + // entry on each medication concept (WHO stays first, byte-identical). When + // omitted, the route derives it from a German-region locale. + germanAtc: z.boolean().optional(), }) .strict();