import { sql } from "drizzle-orm"; import { boolean, index, integer, jsonb, pgEnum, pgTable, primaryKey, text, timestamp, uniqueIndex, uuid, vector, } from "drizzle-orm/pg-core"; export const accountStatusEnum = pgEnum("account_status", ["active", "disabled", "pending"]); export const organizationStatusEnum = pgEnum("organization_status", ["active", "disabled"]); export const roleScopeEnum = pgEnum("role_scope", ["platform", "organization"]); export const membershipStatusEnum = pgEnum("membership_status", ["active", "disabled", "pending"]); export const bedStatusEnum = pgEnum("bed_status", ["available", "occupied", "maintenance", "disabled"]); export const elderStatusEnum = pgEnum("elder_status", ["active", "pending", "discharged"]); export const careLevelEnum = pgEnum("care_level", ["self-care", "semi-assisted", "assisted", "intensive"]); export const genderEnum = pgEnum("gender", ["male", "female", "other"]); export const admissionStatusEnum = pgEnum("admission_status", ["active", "transferred", "discharged"]); export const auditResultEnum = pgEnum("audit_result", ["success", "denied", "failure"]); export const incidentStatusEnum = pgEnum("incident_status", ["open", "acknowledged", "resolved", "closed"]); export const incidentSeverityEnum = pgEnum("incident_severity", ["info", "warning", "critical"]); export const joinRequestStatusEnum = pgEnum("join_request_status", ["pending", "approved", "rejected"]); export const vitalRecordSourceEnum = pgEnum("vital_record_source", ["manual", "device", "import"]); export const chronicConditionStatusEnum = pgEnum("chronic_condition_status", ["active", "controlled", "resolved"]); export const healthReviewStatusEnum = pgEnum("health_review_status", ["pending", "reviewed", "resolved"]); export const careTaskTypeEnum = pgEnum("care_task_type", ["daily_care", "meal", "medication", "rehab", "inspection", "cleaning", "other"]); export const careTaskPriorityEnum = pgEnum("care_task_priority", ["low", "normal", "high", "urgent"]); export const careTaskStatusEnum = pgEnum("care_task_status", ["pending", "in_progress", "completed", "cancelled"]); export const deviceAssetStatusEnum = pgEnum("device_asset_status", ["active", "maintenance", "disabled", "retired"]); export const maintenanceTicketStatusEnum = pgEnum("maintenance_ticket_status", ["open", "assigned", "resolved", "closed", "cancelled"]); export const maintenanceTicketPriorityEnum = pgEnum("maintenance_ticket_priority", ["low", "normal", "high", "urgent"]); export const noticeStatusEnum = pgEnum("notice_status", ["draft", "published", "retracted"]); export const alertRuleTypeEnum = pgEnum("alert_rule_type", ["health", "care", "device", "incident", "admission", "other"]); export const alertRuleStatusEnum = pgEnum("alert_rule_status", ["enabled", "disabled"]); export const alertTriggerStatusEnum = pgEnum("alert_trigger_status", ["open", "acknowledged", "resolved", "closed"]); export const familyContactStatusEnum = pgEnum("family_contact_status", ["active", "suspended", "archived"]); export const familyVisitStatusEnum = pgEnum("family_visit_status", ["requested", "approved", "completed", "cancelled"]); export const familyFeedbackTypeEnum = pgEnum("family_feedback_type", ["service", "care", "meal", "environment", "other"]); export const familyFeedbackStatusEnum = pgEnum("family_feedback_status", ["open", "in_progress", "resolved", "closed"]); export const aiKnowledgeScopeEnum = pgEnum("ai_knowledge_scope", ["platform", "organization"]); export const aiKnowledgeStatusEnum = pgEnum("ai_knowledge_status", ["enabled", "disabled"]); export const elderAiAnalysisStatusEnum = pgEnum("elder_ai_analysis_status", ["completed", "failed"]); export const AI_KNOWLEDGE_EMBEDDING_DIMENSIONS = 1536; export const systemSettings = pgTable("system_settings", { id: text("id").primaryKey().default("global"), registrationEnabled: boolean("registration_enabled").notNull().default(true), oidcEnabled: boolean("oidc_enabled").notNull().default(false), oidcIssuerUrl: text("oidc_issuer_url").notNull().default(""), oidcClientId: text("oidc_client_id").notNull().default(""), oidcClientSecret: text("oidc_client_secret").notNull().default(""), oidcScopes: text("oidc_scopes").notNull().default("openid profile email"), oidcRedirectUri: text("oidc_redirect_uri").notNull().default(""), oidcAvatarClaim: text("oidc_avatar_claim").notNull().default("picture"), oidcAutoProvision: boolean("oidc_auto_provision").notNull().default(false), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const organizations = pgTable("organizations", { id: uuid("id").primaryKey().defaultRandom(), name: text("name").notNull(), slug: text("slug").notNull(), status: organizationStatusEnum("status").notNull().default("active"), registrationEnabled: boolean("registration_enabled").notNull().default(true), oidcEnabled: boolean("oidc_enabled").notNull().default(false), oidcIssuerUrl: text("oidc_issuer_url").notNull().default(""), oidcClientId: text("oidc_client_id").notNull().default(""), oidcClientSecret: text("oidc_client_secret").notNull().default(""), oidcScopes: text("oidc_scopes").notNull().default("openid profile email"), oidcRedirectUri: text("oidc_redirect_uri").notNull().default(""), oidcAvatarClaim: text("oidc_avatar_claim").notNull().default("picture"), oidcAutoProvision: boolean("oidc_auto_provision").notNull().default(false), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ slugUnique: uniqueIndex("organizations_slug_unique").on(table.slug), })); export const permissions = pgTable("permissions", { id: text("id").primaryKey(), label: text("label").notNull(), category: text("category").notNull(), description: text("description").notNull(), isEnabled: boolean("is_enabled").notNull().default(true), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }); export const roles = pgTable("roles", { id: uuid("id").primaryKey().defaultRandom(), key: text("key").notNull(), organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }), scope: roleScopeEnum("scope").notNull(), label: text("label").notNull(), description: text("description").notNull(), isSystem: boolean("is_system").notNull().default(false), isEnabled: boolean("is_enabled").notNull().default(true), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ roleKeyUnique: uniqueIndex("roles_key_organization_unique").on(table.key, table.organizationId), })); export const rolePermissions = pgTable("role_permissions", { roleId: uuid("role_id").notNull().references(() => roles.id, { onDelete: "cascade" }), permissionId: text("permission_id").notNull().references(() => permissions.id, { onDelete: "cascade" }), }, (table) => ({ pk: primaryKey({ columns: [table.roleId, table.permissionId] }), })); export const accounts = pgTable("accounts", { id: uuid("id").primaryKey().defaultRandom(), platformRoleId: uuid("platform_role_id").references(() => roles.id), name: text("name").notNull(), email: text("email").notNull(), avatarUrl: text("avatar_url").notNull().default(""), passwordHash: text("password_hash").notNull(), passwordSalt: text("password_salt").notNull(), status: accountStatusEnum("status").notNull().default("active"), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ emailUnique: uniqueIndex("accounts_email_unique").on(table.email), })); export const memberships = pgTable("memberships", { id: uuid("id").primaryKey().defaultRandom(), accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), roleId: uuid("role_id").notNull().references(() => roles.id), status: membershipStatusEnum("status").notNull().default("active"), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ accountOrganizationUnique: uniqueIndex("memberships_account_organization_unique").on( table.accountId, table.organizationId, ), })); export const sessions = pgTable("sessions", { id: uuid("id").primaryKey().defaultRandom(), accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }), activeOrganizationId: uuid("active_organization_id").references(() => organizations.id), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), }); export const joinRequests = pgTable("join_requests", { id: uuid("id").primaryKey().defaultRandom(), accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), status: joinRequestStatusEnum("status").notNull().default("pending"), reason: text("reason").notNull().default(""), reviewedByAccountId: uuid("reviewed_by_account_id").references(() => accounts.id), reviewedAt: timestamp("reviewed_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }); export const organizationInvitations = pgTable("organization_invitations", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), roleId: uuid("role_id").notNull().references(() => roles.id), email: text("email").notNull().default(""), token: text("token").notNull(), status: text("status").notNull().default("active"), createdByAccountId: uuid("created_by_account_id").references(() => accounts.id), acceptedByAccountId: uuid("accepted_by_account_id").references(() => accounts.id), acceptedAt: timestamp("accepted_at", { withTimezone: true }), expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(), maxUses: integer("max_uses").notNull().default(1), usedCount: integer("used_count").notNull().default(0), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ tokenUnique: uniqueIndex("organization_invitations_token_unique").on(table.token), })); export const campuses = pgTable("campuses", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), name: text("name").notNull(), address: text("address").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const buildings = pgTable("buildings", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), campusId: uuid("campus_id").notNull().references(() => campuses.id, { onDelete: "cascade" }), name: text("name").notNull(), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const floors = pgTable("floors", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), buildingId: uuid("building_id").notNull().references(() => buildings.id, { onDelete: "cascade" }), name: text("name").notNull(), level: integer("level").notNull(), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const rooms = pgTable("rooms", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), floorId: uuid("floor_id").notNull().references(() => floors.id, { onDelete: "cascade" }), name: text("name").notNull(), code: text("code").notNull(), capacity: integer("capacity").notNull().default(1), status: organizationStatusEnum("status").notNull().default("active"), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ roomCodeUnique: uniqueIndex("rooms_code_organization_unique").on(table.organizationId, table.code), })); export const beds = pgTable("beds", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), roomId: uuid("room_id").notNull().references(() => rooms.id, { onDelete: "cascade" }), code: text("code").notNull(), status: bedStatusEnum("status").notNull().default("available"), notes: text("notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ bedCodeUnique: uniqueIndex("beds_code_room_unique").on(table.roomId, table.code), })); export const elders = pgTable("elders", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), name: text("name").notNull(), gender: genderEnum("gender").notNull(), age: integer("age").notNull(), careLevel: careLevelEnum("care_level").notNull(), status: elderStatusEnum("status").notNull().default("pending"), primaryContact: text("primary_contact").notNull(), phone: text("phone").notNull(), medicalNotes: text("medical_notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const healthProfiles = pgTable("health_profiles", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), allergyNotes: text("allergy_notes").notNull().default(""), medicalHistory: text("medical_history").notNull().default(""), medicationNotes: text("medication_notes").notNull().default(""), careRestrictions: text("care_restrictions").notNull().default(""), emergencyNotes: text("emergency_notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ elderUnique: uniqueIndex("health_profiles_organization_elder_unique").on(table.organizationId, table.elderId), })); export const vitalRecords = pgTable("vital_records", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), recordedAt: timestamp("recorded_at", { withTimezone: true }).notNull(), source: vitalRecordSourceEnum("source").notNull().default("manual"), systolicBp: integer("systolic_bp"), diastolicBp: integer("diastolic_bp"), heartRate: integer("heart_rate"), temperatureTenths: integer("temperature_tenths"), spo2: integer("spo2"), bloodGlucoseTenths: integer("blood_glucose_tenths"), weightTenths: integer("weight_tenths"), notes: text("notes").notNull().default(""), createdByAccountId: uuid("created_by_account_id").references(() => accounts.id), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ recentLookup: index("vital_records_recent_lookup").on(table.organizationId, table.elderId, table.recordedAt), })); export const chronicConditions = pgTable("chronic_conditions", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), name: text("name").notNull(), status: chronicConditionStatusEnum("status").notNull().default("active"), diagnosedAt: timestamp("diagnosed_at", { withTimezone: true }), treatmentNotes: text("treatment_notes").notNull().default(""), followUpNotes: text("follow_up_notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ elderStatusLookup: index("chronic_conditions_elder_status_lookup").on(table.organizationId, table.elderId, table.status), })); export const healthAnomalyReviews = pgTable("health_anomaly_reviews", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), vitalRecordId: uuid("vital_record_id").references(() => vitalRecords.id, { onDelete: "set null" }), severity: incidentSeverityEnum("severity").notNull(), status: healthReviewStatusEnum("status").notNull().default("pending"), title: text("title").notNull(), description: text("description").notNull(), reviewedByAccountId: uuid("reviewed_by_account_id").references(() => accounts.id), reviewedAt: timestamp("reviewed_at", { withTimezone: true }), resolutionNotes: text("resolution_notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ reviewQueueLookup: index("health_anomaly_reviews_queue_lookup").on(table.organizationId, table.status, table.severity), })); export const careTasks = pgTable("care_tasks", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").references(() => elders.id, { onDelete: "set null" }), title: text("title").notNull(), careType: careTaskTypeEnum("care_type").notNull(), priority: careTaskPriorityEnum("priority").notNull().default("normal"), status: careTaskStatusEnum("status").notNull().default("pending"), scheduledAt: timestamp("scheduled_at", { withTimezone: true }).notNull(), assigneeLabel: text("assignee_label").notNull().default(""), executionNotes: text("execution_notes").notNull().default(""), completedAt: timestamp("completed_at", { withTimezone: true }), createdByAccountId: uuid("created_by_account_id").references(() => accounts.id), completedByAccountId: uuid("completed_by_account_id").references(() => accounts.id), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ queueLookup: index("care_tasks_queue_lookup").on(table.organizationId, table.status, table.priority), scheduleLookup: index("care_tasks_schedule_lookup").on(table.organizationId, table.scheduledAt), })); export const deviceAssets = pgTable("device_assets", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), name: text("name").notNull(), code: text("code").notNull(), category: text("category").notNull().default(""), location: text("location").notNull().default(""), status: deviceAssetStatusEnum("status").notNull().default("active"), lastInspectedAt: timestamp("last_inspected_at", { withTimezone: true }), notes: text("notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ codeUnique: uniqueIndex("device_assets_code_organization_unique").on(table.organizationId, table.code), statusLookup: index("device_assets_status_lookup").on(table.organizationId, table.status), })); export const maintenanceTickets = pgTable("maintenance_tickets", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), deviceId: uuid("device_id").references(() => deviceAssets.id, { onDelete: "set null" }), title: text("title").notNull(), description: text("description").notNull().default(""), priority: maintenanceTicketPriorityEnum("priority").notNull().default("normal"), status: maintenanceTicketStatusEnum("status").notNull().default("open"), assigneeLabel: text("assignee_label").notNull().default(""), resolutionNotes: text("resolution_notes").notNull().default(""), resolvedAt: timestamp("resolved_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ queueLookup: index("maintenance_tickets_queue_lookup").on(table.organizationId, table.status, table.priority), deviceLookup: index("maintenance_tickets_device_lookup").on(table.organizationId, table.deviceId), })); export const notices = pgTable("notices", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), title: text("title").notNull(), content: text("content").notNull().default(""), audience: text("audience").notNull().default("全体员工"), status: noticeStatusEnum("status").notNull().default("draft"), publishedAt: timestamp("published_at", { withTimezone: true }), createdByAccountId: uuid("created_by_account_id").references(() => accounts.id), updatedByAccountId: uuid("updated_by_account_id").references(() => accounts.id), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ statusLookup: index("notices_status_lookup").on(table.organizationId, table.status), })); export const noticeReadReceipts = pgTable("notice_read_receipts", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), noticeId: uuid("notice_id").notNull().references(() => notices.id, { onDelete: "cascade" }), accountId: uuid("account_id").notNull().references(() => accounts.id, { onDelete: "cascade" }), readAt: timestamp("read_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ accountNoticeUnique: uniqueIndex("notice_read_receipts_account_notice_unique").on(table.noticeId, table.accountId), noticeLookup: index("notice_read_receipts_notice_lookup").on(table.organizationId, table.noticeId), })); export const alertRules = pgTable("alert_rules", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), name: text("name").notNull(), ruleType: alertRuleTypeEnum("rule_type").notNull().default("other"), severity: incidentSeverityEnum("severity").notNull().default("warning"), status: alertRuleStatusEnum("status").notNull().default("enabled"), conditionSummary: text("condition_summary").notNull().default(""), suggestion: text("suggestion").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ statusLookup: index("alert_rules_status_lookup").on(table.organizationId, table.status, table.ruleType), })); export const alertTriggers = pgTable("alert_triggers", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), ruleId: uuid("rule_id").references(() => alertRules.id, { onDelete: "set null" }), elderId: uuid("elder_id").references(() => elders.id, { onDelete: "set null" }), title: text("title").notNull(), description: text("description").notNull().default(""), status: alertTriggerStatusEnum("status").notNull().default("open"), source: text("source").notNull().default(""), handledByAccountId: uuid("handled_by_account_id").references(() => accounts.id), handledAt: timestamp("handled_at", { withTimezone: true }), handlingNotes: text("handling_notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ queueLookup: index("alert_triggers_queue_lookup").on(table.organizationId, table.status), ruleLookup: index("alert_triggers_rule_lookup").on(table.organizationId, table.ruleId), })); export const familyContacts = pgTable("family_contacts", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), name: text("name").notNull(), relationship: text("relationship").notNull(), phone: text("phone").notNull(), status: familyContactStatusEnum("status").notNull().default("active"), notes: text("notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ elderLookup: index("family_contacts_elder_lookup").on(table.organizationId, table.elderId, table.status), })); export const familyVisitAppointments = pgTable("family_visit_appointments", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), contactId: uuid("contact_id").references(() => familyContacts.id, { onDelete: "set null" }), scheduledAt: timestamp("scheduled_at", { withTimezone: true }).notNull(), status: familyVisitStatusEnum("status").notNull().default("requested"), notes: text("notes").notNull().default(""), handledByAccountId: uuid("handled_by_account_id").references(() => accounts.id), handledAt: timestamp("handled_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ scheduleLookup: index("family_visit_appointments_schedule_lookup").on(table.organizationId, table.status, table.scheduledAt), })); export const familyFeedback = pgTable("family_feedback", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), contactId: uuid("contact_id").references(() => familyContacts.id, { onDelete: "set null" }), feedbackType: familyFeedbackTypeEnum("feedback_type").notNull().default("other"), content: text("content").notNull(), status: familyFeedbackStatusEnum("status").notNull().default("open"), responseNotes: text("response_notes").notNull().default(""), handledByAccountId: uuid("handled_by_account_id").references(() => accounts.id), handledAt: timestamp("handled_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ queueLookup: index("family_feedback_queue_lookup").on(table.organizationId, table.status, table.feedbackType), })); export const admissions = pgTable("admissions", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), bedId: uuid("bed_id").notNull().references(() => beds.id), status: admissionStatusEnum("status").notNull().default("active"), admittedAt: timestamp("admitted_at", { withTimezone: true }).notNull().defaultNow(), dischargedAt: timestamp("discharged_at", { withTimezone: true }), notes: text("notes").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const auditLogs = pgTable("audit_logs", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }), timestamp: timestamp("timestamp", { withTimezone: true }).notNull().defaultNow(), actorAccountId: uuid("actor_account_id").references(() => accounts.id), actorEmail: text("actor_email"), action: text("action").notNull(), targetType: text("target_type").notNull(), targetId: text("target_id"), result: auditResultEnum("result").notNull(), reason: text("reason").notNull(), }); export const systemIncidents = pgTable("system_incidents", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }), severity: incidentSeverityEnum("severity").notNull(), status: incidentStatusEnum("status").notNull().default("open"), title: text("title").notNull(), description: text("description").notNull(), source: text("source").notNull(), acknowledgedByAccountId: uuid("acknowledged_by_account_id").references(() => accounts.id), acknowledgedAt: timestamp("acknowledged_at", { withTimezone: true }), resolvedByAccountId: uuid("resolved_by_account_id").references(() => accounts.id), resolvedAt: timestamp("resolved_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }); export const aiKnowledgeEntries = pgTable("ai_knowledge_entries", { id: uuid("id").primaryKey().defaultRandom(), scope: aiKnowledgeScopeEnum("scope").notNull(), organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }), title: text("title").notNull(), category: text("category").notNull().default(""), tags: text("tags").notNull().default(""), body: text("body").notNull(), status: aiKnowledgeStatusEnum("status").notNull().default("enabled"), createdByAccountId: uuid("created_by_account_id").references(() => accounts.id, { onDelete: "set null" }), updatedByAccountId: uuid("updated_by_account_id").references(() => accounts.id, { onDelete: "set null" }), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ scopeLookup: index("ai_knowledge_entries_scope_lookup").on(table.scope, table.status), organizationLookup: index("ai_knowledge_entries_organization_lookup").on(table.organizationId, table.status), })); export const aiKnowledgeChunks = pgTable("ai_knowledge_chunks", { id: uuid("id").primaryKey().defaultRandom(), entryId: uuid("entry_id").notNull().references(() => aiKnowledgeEntries.id, { onDelete: "cascade" }), organizationId: uuid("organization_id").references(() => organizations.id, { onDelete: "cascade" }), scope: aiKnowledgeScopeEnum("scope").notNull(), chunkIndex: integer("chunk_index").notNull(), content: text("content").notNull(), embedding: vector("embedding", { dimensions: AI_KNOWLEDGE_EMBEDDING_DIMENSIONS }).notNull(), sourceTitle: text("source_title").notNull(), sourceCategory: text("source_category").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ entryLookup: index("ai_knowledge_chunks_entry_lookup").on(table.entryId), scopeLookup: index("ai_knowledge_chunks_scope_lookup").on(table.scope, table.organizationId), })); export const elderAiAnalyses = pgTable("elder_ai_analyses", { id: uuid("id").primaryKey().defaultRandom(), organizationId: uuid("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }), elderId: uuid("elder_id").notNull().references(() => elders.id, { onDelete: "cascade" }), actorAccountId: uuid("actor_account_id").references(() => accounts.id, { onDelete: "set null" }), status: elderAiAnalysisStatusEnum("status").notNull(), dataScopes: jsonb("data_scopes").$type().notNull().default(sql`'[]'::jsonb`), resultJson: jsonb("result_json"), citationsJson: jsonb("citations_json").notNull().default(sql`'[]'::jsonb`), modelSummaryJson: jsonb("model_summary_json").notNull().default(sql`'{}'::jsonb`), errorCategory: text("error_category").notNull().default(""), errorReason: text("error_reason").notNull().default(""), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ elderLookup: index("elder_ai_analyses_elder_lookup").on(table.organizationId, table.elderId, table.createdAt), statusLookup: index("elder_ai_analyses_status_lookup").on(table.organizationId, table.status), }));