// (related-person financial disclosure) - the pure half of useCurrentBillingAccess, kept free of // React/HTTP imports so it is testable without rendering or context (same split as // relatedPersonAuthority.ts / careAccess.helpers.ts). import type { MyProxy } from './useMyProxies.tsx'; export interface BillingAccess { /** May SEE the displayed patient's invoices and payments. */ canView: boolean; /** May PAY on the displayed patient's behalf. Implies canView. */ canPay: boolean; } export const NO_BILLING_ACCESS: BillingAccess = { canView: false, canPay: false }; /** A patient always has full access to their OWN money - changes nothing for the self case. */ export const SELF_BILLING_ACCESS: BillingAccess = { canView: true, canPay: true }; /** * Resolve the billing access that applies to whoever's record is currently on screen. * * Three cases, in order: * 1. The displayed patient IS the logged-in patient full self access. Unchanged by. * 2. The displayed patient is someone the caller proxies that proxy row's granted flags. * 3. Anything else - no displayed patient, no matching proxy row, a still-loading list, or a row from a * pre-028 deployment with no flags at all DENIED. * * Case 3 is the whole point: this is a UX gate over a server boundary, so "I don't know yet" and "not * granted" must look identical. Showing a surface optimistically would render a page whose every request * 403s; hiding it costs at most one render while the proxy list loads. */ export const resolveBillingAccess = ( displayedPatientId: string | undefined, loggedInPatientId: string | undefined, proxies: MyProxy[] | undefined, ): BillingAccess => { if (!displayedPatientId) return NO_BILLING_ACCESS; if (loggedInPatientId && displayedPatientId === loggedInPatientId) { return SELF_BILLING_ACCESS; } const proxy = (proxies ?? []).find((entry) => entry.subjectPatientId === displayedPatientId); if (!proxy) return NO_BILLING_ACCESS; const canView = proxy.allowBillingView === true; // pay view, mirrored from the server so a malformed row can never yield pay-without-view. return { canView, canPay: canView && proxy.allowBillingPay === true }; };