export type Role = "SUPER_USER" | "HR_ADMIN" | "FINANCE" | "MEMBER"; export type LocaleCode = "en" | "am"; export type OrgStatus = | "pending_activation" | "active" | "suspended" | "closed"; export type MemberStatus = "invited" | "active" | "inactive" | "offboarded"; export type PrescriptionStatus = | "submitted" | "under_review" | "approved" | "queried" | "rejected"; export type MigrationDataset = | "departments" | "packages" | "members" | "overrides" | "dependants" | "verification_ids" | "full_onboarding"; export type MigrationJobStatus = | "draft" | "validating" | "preview" | "committing" | "completed" | "failed" | "rolled_back"; export type ApprovalStatus = "pending" | "approved" | "flagged" | "rejected"; export type ContactChannel = "email" | "phone"; export interface SessionUser { id: string; email: string; name: string; roles: Role[]; activeRole: Role; orgId: string; memberId?: string; locale: LocaleCode; avatarInitials: string; /** Optional profile photo; demos use deterministic DiceBear URLs */ avatarUrl?: string; } export interface Organisation { id: string; legalName: string; tradeName: string; tin: string; status: OrgStatus; billingEmail: string; billingPhone: string; approxHeadcount: number; creditLimitEtb: number | null; creditUsedEtb: number; paymentTermsDays: number | null; priceListCode: string | null; contractStart: string | null; contractEnd: string | null; joinCode: string; allowedEmailDomains: string[]; verificationMethod: "member_id" | "qr" | "phone_otp" | "none"; maxDependantsPerMember: number; createdAt: string; } export interface OrgRegistrationRequest { id: string; contactName: string; organisationName: string; channel: ContactChannel; email?: string; phone?: string; notes?: string; status: "new" | "in_progress" | "converted" | "closed"; createdAt: string; } export interface Department { id: string; orgId: string; name: string; siteName: string; parentId: string | null; subLimitEtb: number | null; spendEtb: number; memberCount: number; } export interface BenefitPackage { id: string; orgId: string; code: string; name: string; monthlyAllowanceEtb: number; copayPercent: number; categories: string[]; exclusions: string[]; perks: string[]; annualCapEtb: number | null; active: boolean; memberCount: number; } export interface MemberOverride { memberId: string; monthlyAllowanceEtb?: number; copayPercent?: number; categories?: string[]; notes?: string; } export interface Dependant { id: string; memberId: string; name: string; relationship: "spouse" | "child" | "parent" | "other"; dateOfBirth: string; status: MemberStatus; } export interface Member { id: string; orgId: string; customerId: string; employeeId: string; name: string; email: string; phone: string; departmentId: string; packageId: string; status: MemberStatus; startDate: string; allowanceRemainingEtb: number; allowanceTotalEtb: number; override?: MemberOverride; dependants: Dependant[]; verificationId?: string; /** Pharmacy ID card number shown on printable badge (e.g. GSH-1001) */ cardId?: string; /** Optional profile photo; demos use deterministic DiceBear URLs */ avatarUrl?: string; /** Clinical fields — withheld from HR_ADMIN / FINANCE */ hasActiveRx?: boolean; lastRxStatus?: PrescriptionStatus; } export interface SpendRow { id: string; orgId: string; memberId: string; memberName: string; departmentId: string; departmentName: string; category: string; amountEtb: number; coveredEtb: number; memberPaidEtb: number; orderRef: string; occurredAt: string; /** Never expose Rx line items to HR/Finance */ clinicalSummaryWithheld: true; } export interface Statement { id: string; orgId: string; period: string; totalSpendEtb: number; coveredEtb: number; creditUsedEtb: number; status: "draft" | "issued" | "paid"; issuedAt: string | null; } export interface ApprovalRequest { id: string; orgId: string; memberName: string; departmentName: string; amountEtb: number; thresholdEtb: number; reason: string; status: ApprovalStatus; createdAt: string; } export interface MemberOrder { id: string; memberId: string; placedAt: string; status: "placed" | "processing" | "delivered" | "cancelled"; totalEtb: number; coveredEtb: number; memberPaidEtb: number; itemCount: number; } export interface Prescription { id: string; memberId: string; status: PrescriptionStatus; submittedAt: string; updatedAt: string; pageCount: number; daysOfSupply?: number; pharmacistNote?: string; /** File names only in mock — real blobs go to storage */ fileNames: string[]; } export interface LoyaltySummary { points: number; tier: string; note: string; } export interface MigrationJob { id: string; orgId: string; dataset: MigrationDataset; status: MigrationJobStatus; fileName: string; createdBy: string; createdAt: string; rowCount: number; createCount: number; updateCount: number; skipCount: number; errorCount: number; errors: { row: number; field: string; message: string }[]; } export interface Paginated { data: T[]; page: number; pageSize: number; total: number; } export interface ApiError { code: string; message: string; details?: Record; }