import { randomUUID } from "node:crypto"; import { and, desc, eq } from "drizzle-orm"; import { jsonFailure, jsonSuccess, readJsonBody } from "@/modules/core/server/api"; import { recordAuditLog } from "@/modules/core/server/audit"; import { requirePermission } from "@/modules/core/server/auth"; import { getDatabase } from "@/modules/core/server/db"; import { admissions, beds, elders, rooms } from "@/modules/core/server/schema"; import { validateElderInput } from "@/modules/elders/types"; import type { Elder } from "@/modules/elders/types"; type ElderRow = typeof elders.$inferSelect; type BedLabel = { room: string; bed: string; bedId: string; }; type ElderCreateResult = | { success: true; elder: ElderRow; bedLabel?: BedLabel; } | { success: false; reason: string; status: number; }; function toElder(row: ElderRow, bedLabel?: BedLabel): Elder { return { id: row.id, organizationId: row.organizationId, name: row.name, gender: row.gender, age: row.age, careLevel: row.careLevel, room: bedLabel?.room ?? "", bed: bedLabel?.bed ?? "", bedId: bedLabel?.bedId, status: row.status, primaryContact: row.primaryContact, phone: row.phone, medicalNotes: row.medicalNotes, createdAt: row.createdAt.toISOString(), updatedAt: row.updatedAt.toISOString(), }; } export async function GET(): Promise { const auth = await requirePermission("elder:read", { action: "elder.list", targetType: "elder", }); if (!auth.success) { return auth.response; } const organizationId = auth.context.organization?.id; if (!organizationId) { return jsonFailure("请选择机构后查看老人档案", 400); } const database = getDatabase(); const [rows, activeAdmissionRows] = await Promise.all([ database .select() .from(elders) .where(eq(elders.organizationId, organizationId)) .orderBy(desc(elders.createdAt)), database .select({ elderId: admissions.elderId, bedId: admissions.bedId, bedCode: beds.code, roomName: rooms.name, }) .from(admissions) .innerJoin(beds, eq(beds.id, admissions.bedId)) .innerJoin(rooms, eq(rooms.id, beds.roomId)) .where(and(eq(admissions.organizationId, organizationId), eq(admissions.status, "active"))), ]); const bedLabelByElderId = new Map( activeAdmissionRows.map((row) => [ row.elderId, { room: row.roomName, bed: row.bedCode, bedId: row.bedId, }, ]), ); return jsonSuccess("老人档案已加载", { elders: rows.map((row) => toElder(row, bedLabelByElderId.get(row.id))) }); } export async function POST(request: Request): Promise { const auth = await requirePermission("elder:create", { action: "elder.create", targetType: "elder", }); if (!auth.success) { return auth.response; } const organizationId = auth.context.organization?.id; if (!organizationId) { return jsonFailure("请选择机构后新增老人档案", 400); } const input = validateElderInput(await readJsonBody(request)); if (!input.success) { return jsonFailure(input.reason); } const database = getDatabase(); const created = await database.transaction(async (transaction): Promise => { const elderId = randomUUID(); const elderRows = await transaction .insert(elders) .values({ id: elderId, organizationId, name: input.data.name, gender: input.data.gender, age: input.data.age, careLevel: input.data.careLevel, status: input.data.bedId ? "active" : input.data.status, primaryContact: input.data.primaryContact, phone: input.data.phone, medicalNotes: input.data.medicalNotes, }) .returning(); const elder = elderRows[0]; if (!elder) { return { success: false, reason: "老人档案创建失败", status: 500 }; } if (input.data.bedId) { const bedRows = await transaction .select({ bed: beds, roomName: rooms.name }) .from(beds) .innerJoin(rooms, eq(rooms.id, beds.roomId)) .where(and(eq(beds.id, input.data.bedId), eq(beds.organizationId, organizationId))) .limit(1); const bedRow = bedRows[0]; if (!bedRow) { return { success: false, reason: "床位不存在", status: 404 }; } if (bedRow.bed.status !== "available") { return { success: false, reason: "床位不可分配", status: 409 }; } await transaction .insert(admissions) .values({ organizationId, elderId: elder.id, bedId: bedRow.bed.id, status: "active", notes: "新增档案时办理入住", }); await transaction .update(beds) .set({ status: "occupied", updatedAt: new Date() }) .where(and(eq(beds.id, bedRow.bed.id), eq(beds.organizationId, organizationId))); return { success: true, elder, bedLabel: { room: bedRow.roomName, bed: bedRow.bed.code, bedId: bedRow.bed.id, }, }; } return { success: true, elder }; }); if (!created.success) { return jsonFailure(created.reason, created.status); } const elder = toElder(created.elder, created.bedLabel); await recordAuditLog({ actor: auth.context.account, organizationId, action: "elder.create", targetType: "elder", targetId: elder.id, result: "success", reason: `新增老人档案:${elder.name}`, }); return jsonSuccess("老人档案已创建", { elder }, 201); }