import { desc, eq, sql } from "drizzle-orm"; import { listAuditLogs } from "@/modules/core/server/audit"; import { getDatabase } from "@/modules/core/server/db"; import { accounts, admissions, beds, elders, memberships, organizations, roles, rooms, sessions, systemIncidents, } from "@/modules/core/server/schema"; import type { Account, Admission, AppData, FacilityBed, Membership, Organization, Room, Session, SystemIncident } from "@/modules/core/types"; import type { Elder } from "@/modules/elders/types"; function iso(value: Date): string { return value.toISOString(); } export async function readData(): Promise { const database = getDatabase(); const [ organizationRows, accountRows, membershipRows, sessionRows, elderRows, roomRows, bedRows, admissionRows, auditLogRows, incidentRows, ] = await Promise.all([ database.select().from(organizations).orderBy(desc(organizations.createdAt)), database.select().from(accounts).orderBy(desc(accounts.createdAt)), database.select({ membership: memberships, role: roles }).from(memberships).innerJoin(roles, eq(roles.id, memberships.roleId)), database.select().from(sessions).orderBy(desc(sessions.createdAt)), database.select().from(elders).orderBy(desc(elders.createdAt)), database.select().from(rooms).orderBy(desc(rooms.createdAt)), database .select({ bed: beds, roomName: rooms.name, currentElderName: sql`( select ${elders.name} from ${admissions} inner join ${elders} on ${elders.id} = ${admissions.elderId} where ${admissions.bedId} = ${beds.id} and ${admissions.status} = 'active' limit 1 )`, }) .from(beds) .innerJoin(rooms, eq(rooms.id, beds.roomId)) .orderBy(desc(beds.createdAt)), database .select({ admission: admissions, elderName: elders.name, bedCode: beds.code, roomName: rooms.name, }) .from(admissions) .innerJoin(elders, eq(elders.id, admissions.elderId)) .innerJoin(beds, eq(beds.id, admissions.bedId)) .innerJoin(rooms, eq(rooms.id, beds.roomId)) .orderBy(desc(admissions.admittedAt)), listAuditLogs({ limit: 100 }), database.select().from(systemIncidents).orderBy(desc(systemIncidents.createdAt)), ]); const roleById = new Map(membershipRows.map((row) => [row.membership.id, row.role])); const bedCounts = new Map(); for (const row of bedRows) { const current = bedCounts.get(row.bed.roomId) ?? { total: 0, occupied: 0 }; current.total += 1; if (row.bed.status === "occupied") { current.occupied += 1; } bedCounts.set(row.bed.roomId, current); } const organizationsData: Organization[] = organizationRows.map((row) => ({ id: row.id, name: row.name, slug: row.slug, status: row.status, createdAt: iso(row.createdAt), updatedAt: iso(row.updatedAt), })); const accountsData: Account[] = accountRows.map((row) => ({ id: row.id, platformRoleId: row.platformRoleId ?? undefined, name: row.name, email: row.email, role: row.platformRoleId ?? "viewer", passwordHash: row.passwordHash, passwordSalt: row.passwordSalt, status: row.status, createdAt: iso(row.createdAt), updatedAt: iso(row.updatedAt), })); const membershipsData: Membership[] = membershipRows.map((row) => { const role = roleById.get(row.membership.id) ?? row.role; return { id: row.membership.id, accountId: row.membership.accountId, organizationId: row.membership.organizationId, roleId: row.membership.roleId, roleKey: role.key, roleLabel: role.label, status: row.membership.status, createdAt: iso(row.membership.createdAt), updatedAt: iso(row.membership.updatedAt), }; }); const sessionsData: Session[] = sessionRows.map((row) => ({ id: row.id, accountId: row.accountId, activeOrganizationId: row.activeOrganizationId ?? undefined, createdAt: iso(row.createdAt), expiresAt: iso(row.expiresAt), })); const eldersData: Elder[] = elderRows.map((row) => ({ id: row.id, organizationId: row.organizationId, name: row.name, gender: row.gender, age: row.age, careLevel: row.careLevel, room: "", bed: "", status: row.status, primaryContact: row.primaryContact, phone: row.phone, medicalNotes: row.medicalNotes, createdAt: iso(row.createdAt), updatedAt: iso(row.updatedAt), })); const roomsData: Room[] = roomRows.map((row) => { const counts = bedCounts.get(row.id) ?? { total: 0, occupied: 0 }; return { id: row.id, organizationId: row.organizationId, name: row.name, code: row.code, capacity: row.capacity, status: row.status, bedCount: counts.total, occupiedBedCount: counts.occupied, createdAt: iso(row.createdAt), updatedAt: iso(row.updatedAt), }; }); const bedsData: FacilityBed[] = bedRows.map((row) => ({ id: row.bed.id, organizationId: row.bed.organizationId, roomId: row.bed.roomId, roomName: row.roomName, code: row.bed.code, status: row.bed.status, notes: row.bed.notes, currentElderName: row.currentElderName ?? undefined, createdAt: iso(row.bed.createdAt), updatedAt: iso(row.bed.updatedAt), })); const admissionsData: Admission[] = admissionRows.map((row) => ({ id: row.admission.id, organizationId: row.admission.organizationId, elderId: row.admission.elderId, elderName: row.elderName, bedId: row.admission.bedId, bedCode: row.bedCode, roomName: row.roomName, status: row.admission.status, admittedAt: iso(row.admission.admittedAt), dischargedAt: row.admission.dischargedAt ? iso(row.admission.dischargedAt) : undefined, notes: row.admission.notes, })); const incidentsData: SystemIncident[] = incidentRows.map((row) => ({ id: row.id, organizationId: row.organizationId ?? undefined, severity: row.severity, status: row.status, title: row.title, description: row.description, source: row.source, createdAt: iso(row.createdAt), updatedAt: iso(row.updatedAt), })); return { organizations: organizationsData, accounts: accountsData, memberships: membershipsData, sessions: sessionsData, elders: eldersData, rooms: roomsData, beds: bedsData, admissions: admissionsData, auditLogs: auditLogRows, incidents: incidentsData, }; } export async function writeData(): Promise { throw new Error("writeData is not available after PostgreSQL migration"); } export async function updateData(): Promise { throw new Error("updateData is not available after PostgreSQL migration"); }