/** * The front desk's "checkout done" stamp on an appointment: who finished checkout and when. The visit * itself stays fulfilled; this only says the desk has nothing left to do for it. */ import type { Appointment, Encounter } from "fhir/r4"; export const APPOINTMENT_CHECKOUT_EXTENSION_URL = "https://akashichealthrecords.com/fhir/StructureDefinition/appointment-checkout-done"; export interface CheckoutDone { reference: string; display?: string; at: string; } export const readCheckoutDone = (appointment: Appointment | undefined): CheckoutDone | undefined => { for (const extension of appointment?.extension ?? []) { if (extension.url !== APPOINTMENT_CHECKOUT_EXTENSION_URL) continue; const children = extension.extension ?? []; const by = children.find((child) => child.url === "by")?.valueReference; const at = children.find((child) => child.url === "at")?.valueDateTime; if (!by?.reference || !at) continue; return by.display ? { reference: by.reference, display: by.display, at } : { reference: by.reference, at }; } return undefined; }; export const withCheckoutDone = (appointment: Appointment, done: CheckoutDone): Appointment => ({ ...appointment, extension: [ ...(appointment.extension ?? []).filter((extension) => extension.url !== APPOINTMENT_CHECKOUT_EXTENSION_URL), { url: APPOINTMENT_CHECKOUT_EXTENSION_URL, extension: [ { url: "by", valueReference: done.display ? { reference: done.reference, display: done.display } : { reference: done.reference }, }, { url: "at", valueDateTime: done.at }, ], }, ], }); /** A finished visit the desk has not yet marked checkout done for. */ export const awaitsCheckout = (appointment: Appointment | undefined, encounter: Encounter | undefined): boolean => Boolean(appointment) && encounter?.status === "finished" && !readCheckoutDone(appointment);