fix: tighten real operations data paths

This commit is contained in:
2026-07-02 19:16:29 -07:00
parent 8b2fb0930e
commit 5fe7e5a1b8
8 changed files with 286 additions and 117 deletions

View File

@@ -0,0 +1,203 @@
import { and, desc, eq, isNull, or, sql } from "drizzle-orm";
import { getDatabase } from "@/modules/core/server/db";
import { admissions, beds, elders, rooms, systemIncidents } from "@/modules/core/server/schema";
import type { Admission, FacilityBed, Room, SystemIncident } from "@/modules/core/types";
import type { Elder } from "@/modules/elders/types";
function iso(value: Date): string {
return value.toISOString();
}
type ActiveBedLabel = {
bed: string;
bedId: string;
room: string;
};
function toElder(row: typeof elders.$inferSelect, activeBed?: ActiveBedLabel): Elder {
return {
id: row.id,
organizationId: row.organizationId,
name: row.name,
gender: row.gender,
age: row.age,
careLevel: row.careLevel,
room: activeBed?.room ?? "",
bed: activeBed?.bed ?? "",
bedId: activeBed?.bedId,
status: row.status,
primaryContact: row.primaryContact,
phone: row.phone,
medicalNotes: row.medicalNotes,
createdAt: iso(row.createdAt),
updatedAt: iso(row.updatedAt),
};
}
export async function listOperationalElders(organizationId?: string): Promise<Elder[]> {
const database = getDatabase();
const [elderRows, activeAdmissionRows] = await Promise.all([
database
.select()
.from(elders)
.where(organizationId ? eq(elders.organizationId, organizationId) : sql`true`)
.orderBy(desc(elders.createdAt)),
database
.select({
bedCode: beds.code,
bedId: admissions.bedId,
elderId: admissions.elderId,
roomName: rooms.name,
})
.from(admissions)
.innerJoin(beds, eq(beds.id, admissions.bedId))
.innerJoin(rooms, eq(rooms.id, beds.roomId))
.where(
organizationId
? and(eq(admissions.organizationId, organizationId), eq(admissions.status, "active"))
: eq(admissions.status, "active"),
)
.orderBy(desc(admissions.admittedAt)),
]);
const bedLabelByElderId = new Map<string, ActiveBedLabel>();
for (const row of activeAdmissionRows) {
if (bedLabelByElderId.has(row.elderId)) {
continue;
}
bedLabelByElderId.set(row.elderId, {
room: row.roomName,
bed: row.bedCode,
bedId: row.bedId,
});
}
return elderRows.map((row) => toElder(row, bedLabelByElderId.get(row.id)));
}
export async function listOperationalRooms(organizationId?: string): Promise<Room[]> {
const database = getDatabase();
const [roomRows, bedRows] = await Promise.all([
database
.select()
.from(rooms)
.where(organizationId ? eq(rooms.organizationId, organizationId) : sql`true`)
.orderBy(desc(rooms.createdAt)),
database
.select()
.from(beds)
.where(organizationId ? eq(beds.organizationId, organizationId) : sql`true`),
]);
const bedCounts = new Map<string, { occupied: number; total: number }>();
for (const bed of bedRows) {
const current = bedCounts.get(bed.roomId) ?? { occupied: 0, total: 0 };
current.total += 1;
if (bed.status === "occupied") {
current.occupied += 1;
}
bedCounts.set(bed.roomId, current);
}
return roomRows.map((room) => {
const counts = bedCounts.get(room.id) ?? { occupied: 0, total: 0 };
return {
id: room.id,
organizationId: room.organizationId,
name: room.name,
code: room.code,
capacity: room.capacity,
status: room.status,
bedCount: counts.total,
occupiedBedCount: counts.occupied,
createdAt: iso(room.createdAt),
updatedAt: iso(room.updatedAt),
};
});
}
export async function listOperationalBeds(organizationId?: string): Promise<FacilityBed[]> {
const database = getDatabase();
const bedRows = await database
.select({
bed: beds,
currentElderName: sql<string | null>`(
select ${elders.name}
from ${admissions}
inner join ${elders} on ${elders.id} = ${admissions.elderId}
where ${admissions.bedId} = ${beds.id} and ${admissions.status} = 'active'
order by ${admissions.admittedAt} desc
limit 1
)`,
roomName: rooms.name,
})
.from(beds)
.innerJoin(rooms, eq(rooms.id, beds.roomId))
.where(organizationId ? eq(beds.organizationId, organizationId) : sql`true`)
.orderBy(desc(beds.createdAt));
return 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),
}));
}
export async function listOperationalAdmissions(organizationId?: string): Promise<Admission[]> {
const database = getDatabase();
const admissionRows = await database
.select({
admission: admissions,
bedCode: beds.code,
elderName: elders.name,
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))
.where(organizationId ? eq(admissions.organizationId, organizationId) : sql`true`)
.orderBy(desc(admissions.admittedAt));
return 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,
}));
}
export async function listOperationalIncidents(organizationId?: string): Promise<SystemIncident[]> {
const database = getDatabase();
const incidentRows = await database
.select()
.from(systemIncidents)
.where(organizationId ? or(isNull(systemIncidents.organizationId), eq(systemIncidents.organizationId, organizationId)) : sql`true`)
.orderBy(desc(systemIncidents.createdAt));
return incidentRows.map((incident) => ({
id: incident.id,
organizationId: incident.organizationId ?? undefined,
severity: incident.severity,
status: incident.status,
title: incident.title,
description: incident.description,
source: incident.source,
createdAt: iso(incident.createdAt),
updatedAt: iso(incident.updatedAt),
}));
}