import type { Organization } from 'fhir/r4'; /** * A practice's declaration of whether its programs are 42 CFR Part 2 programs. The server writes it only through * `PUT /R4/Organization/part2-attestation-settings` (Admins of their own practice, bound to the version it read, and * audited); every ordinary Organization write keeps the stored one. This reads it the way the server does * (`shareClassification.readPart2Attestation`), so the screen never shows a declaration the server would not use. */ export const PART2_ATTESTATION_URL = 'https://akashichealthrecords.com/fhir/extensions/part2-program-attestation'; export const PART2_STATUSES = ['part2', 'not-part2', 'mixed'] as const; export type Part2Status = (typeof PART2_STATUSES)[number]; export interface Part2Declaration { status: Part2Status; coversAllPrograms: boolean; version: string; effectiveFrom?: string; attestedAt?: string; } /** What is on file: a declaration, none at all, or one the server would not use. */ export type Part2OnFile = | { kind: 'declared'; declaration: Part2Declaration } | { kind: 'none' } | { kind: 'unusable' }; /** * What the save sends. The three answers are the administrator's own; nothing is filled in for them. `expectedVersion` * is the declaration they answered against - its version, or null when none was readable on file - and the server * refuses (409 `declaration-changed`) when another has been stored since, so one Admin never overwrites another unseen. */ export interface Part2DeclarationAnswer { status: Part2Status; coversAllPrograms: boolean; effectiveFrom: string; expectedVersion: string | null; } export const PART2_STATUS_LABELS: Record = { part2: 'A Part 2 program', 'not-part2': 'Not a Part 2 program', mixed: 'Mixed', }; export const readPart2OnFile = (organization: Organization | undefined): Part2OnFile => { const extension = organization?.extension?.find((e) => e.url === PART2_ATTESTATION_URL); if (!extension) return { kind: 'none' }; const sub = (url: string) => extension.extension?.find((e) => e.url === url); const status = sub('status')?.valueCode; const version = sub('version')?.valueString; if (!PART2_STATUSES.includes(status as Part2Status) || !version) return { kind: 'unusable' }; return { kind: 'declared', declaration: { status: status as Part2Status, coversAllPrograms: sub('coversAllPrograms')?.valueBoolean === true, version, effectiveFrom: sub('effectiveFrom')?.valueDateTime, attestedAt: sub('attestedAt')?.valueDateTime, }, }; }; /** The version the server checks a save against: the one shown, or null for none and for one it would not use. */ export const expectedVersionOf = (onFile: Part2OnFile): string | null => (onFile.kind === 'declared' ? onFile.declaration.version : null); /** The server's refusal of a save answered against a declaration that is no longer the one on file. */ export const isDeclarationChanged = (error: unknown): boolean => { const failure = error as { status?: unknown; body?: { code?: unknown } } | null; return failure?.status === 409 && failure.body?.code === 'declaration-changed'; }; /** The version a save is checked against here, before sending: the declaration that was on screen when they chose. */ export const onFileVersion = (onFile: Part2OnFile): string => (onFile.kind === 'declared' ? onFile.declaration.version : onFile.kind);