diff --git a/src/lib/doctor-report-data.ts b/src/lib/doctor-report-data.ts index 8e5cb0f23..e2c71a303 100644 --- a/src/lib/doctor-report-data.ts +++ b/src/lib/doctor-report-data.ts @@ -130,8 +130,9 @@ export interface DoctorReportData { deliveryForm: string | null; }>; /** - * v1.9.0 — set when {@link MAX_MEDICATION_ADMINISTRATIONS} trimmed the - * administration set. `total` is the full acted-intake count over the + * v1.9.0 — set when the administration cap (see + * {@link resolveMaxMedicationAdministrations}) trimmed the administration + * set. `total` is the full acted-intake count over the * window; `included` is how many (the most-recent) survived the cap. * Null/absent when nothing was trimmed. The FHIR builder discloses * this in the document narrative so the export is honest about the @@ -265,17 +266,6 @@ export function resolveMaxMedicationAdministrations( : DEFAULT_MAX_MEDICATION_ADMINISTRATIONS; } -/** - * The cap is a coarse safety ceiling resolved once at module load, not a - * per-request knob — the report window is the natural bound; this only - * guards a pathological multi-year, many-medication export. When it trims - * rows the aggregator flags it so the FHIR narrative discloses the - * truncation rather than silently dropping history. - */ -const MAX_MEDICATION_ADMINISTRATIONS = resolveMaxMedicationAdministrations( - process.env.FHIR_MAX_MEDICATION_ADMINISTRATIONS, -); - export interface DoctorReportRange { /** Start of the reporting window (UTC, inclusive). */ start: Date; @@ -594,13 +584,20 @@ export async function collectDoctorReportData( // `scheduledFor: asc`, so the most-recent acted rows are at the tail; // keep the last N and flag the trim so the FHIR narrative can disclose // it. The omitted rows are the OLDEST in the window — recent adherence - // is preserved intact. + // is preserved intact. The cap is a coarse safety ceiling (the report + // window is the natural bound; this only guards a pathological + // multi-year, many-medication export) — resolved per call from + // `FHIR_MAX_MEDICATION_ADMINISTRATIONS` so an operator override takes + // effect without a code change. + const maxMedicationAdministrations = resolveMaxMedicationAdministrations( + process.env.FHIR_MAX_MEDICATION_ADMINISTRATIONS, + ); const totalAdministrations = medicationAdministrations.length; const medicationAdministrationsTruncated = - totalAdministrations > MAX_MEDICATION_ADMINISTRATIONS; + totalAdministrations > maxMedicationAdministrations; const cappedAdministrations = medicationAdministrationsTruncated ? medicationAdministrations.slice( - totalAdministrations - MAX_MEDICATION_ADMINISTRATIONS, + totalAdministrations - maxMedicationAdministrations, ) : medicationAdministrations; diff --git a/tests/integration/doctor-report-sections.test.ts b/tests/integration/doctor-report-sections.test.ts index 73ecdf2da..a905ce4f6 100644 --- a/tests/integration/doctor-report-sections.test.ts +++ b/tests/integration/doctor-report-sections.test.ts @@ -55,6 +55,7 @@ beforeEach(async () => { afterEach(() => { vi.restoreAllMocks(); + vi.unstubAllEnvs(); }); const RANGE = { @@ -241,7 +242,11 @@ describe("doctor-report — per-section toggles", () => { }); describe("doctor-report — MedicationAdministration export cap", () => { - it("caps the administration set at 1000 most-recent rows and flags the truncation", async () => { + it("caps the administration set at the configured ceiling and flags the truncation", async () => { + // The default ceiling is 5000; pin the operator-configurable + // `FHIR_MAX_MEDICATION_ADMINISTRATIONS` to 1000 so the cap is exercised + // with a tractable row count (the cap is resolved per call). + vi.stubEnv("FHIR_MAX_MEDICATION_ADMINISTRATIONS", "1000"); const prisma = getPrismaClient(); const user = await prisma.user.create({ data: {